xref: /xnu-12377.1.9/tests/skywalk/skt_shutdown2.c (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1 /*
2  * Copyright (c) 2017-2024 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <uuid/uuid.h>
35 #include <sys/select.h>
36 #include <poll.h>
37 #include <sys/event.h>
38 #include <sys/sysctl.h>
39 #include <pthread.h>
40 #include <darwintest.h>
41 #include "skywalk_test_driver.h"
42 #include "skywalk_test_common.h"
43 #include "skywalk_test_utils.h"
44 
45 /* Gets channel waiting in kevent/poll/select and then shuts down channel */
46 
47 static void *
thread1(void * unused)48 thread1(void *unused)
49 {
50 	int error;
51 	usleep(100000); /* Make sure main thread gets into kevent */
52 	//sleep(5); /* Make sure main thread gets into kevent */
53 	T_LOG("shutdown sockets\n");
54 	error = pid_shutdown_sockets(getpid(), SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL);
55 	SKTC_ASSERT_ERR(!error);
56 	return NULL;
57 }
58 
59 static int
skt_shutdown2_common(int argc,char * argv[],int method)60 skt_shutdown2_common(int argc, char *argv[], int method)
61 {
62 	int error;
63 	channel_t channel;
64 	uuid_t channel_uuid;
65 	int channelfd;
66 	fd_set rfdset, efdset;
67 	struct pollfd fds;
68 	int kq;
69 	pthread_t thread;
70 	struct kevent kev;
71 
72 	error = uuid_parse(argv[3], channel_uuid);
73 	SKTC_ASSERT_ERR(!error);
74 
75 	channel = sktu_channel_create_extended(channel_uuid, 0,
76 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
77 	    -1, -1, -1, -1, -1, -1, 1, -1, -1);
78 	assert(channel);
79 
80 	channelfd = os_channel_get_fd(channel);
81 	assert(channelfd != -1);
82 
83 	error = pthread_create(&thread, NULL, &thread1, NULL);
84 	SKTC_ASSERT_ERR(error == 0);
85 
86 	switch (method) {
87 	case 0:
88 		FD_ZERO(&rfdset);
89 		FD_ZERO(&efdset);
90 		FD_SET(channelfd, &rfdset);
91 		FD_SET(channelfd, &efdset);
92 		error = select(channelfd + 1, &rfdset, NULL, &efdset, NULL);
93 		SKTC_ASSERT_ERR(error != -1);
94 		SKTC_ASSERT_ERR(error == 1);
95 		assert(!FD_ISSET(channelfd, &rfdset));
96 		assert(FD_ISSET(channelfd, &efdset));
97 		break;
98 	case 1:
99 		fds.fd = channelfd;
100 		fds.events = POLLRDNORM;
101 		fds.revents = 0;
102 		error = poll(&fds, 1, -1);
103 		SKTC_ASSERT_ERR(error != -1);
104 		SKTC_ASSERT_ERR(error == 1);
105 		assert(fds.fd == channelfd);
106 		assert(fds.events == POLLRDNORM);
107 		assert(fds.revents == (POLLRDNORM | POLLHUP));
108 		break;
109 	case 2:
110 		kq = kqueue();
111 		assert(kq != -1);
112 		EV_SET(&kev, channelfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
113 		    NULL);
114 		error = kevent(kq, &kev, 1, &kev, 1, NULL);
115 		SKTC_ASSERT_ERR(error != -1);
116 		SKTC_ASSERT_ERR(error == 1);
117 		assert(kev.filter == EVFILT_READ);
118 		assert(kev.ident == channelfd);
119 		assert(kev.udata == NULL);
120 		assert(kev.flags & EV_EOF);
121 		assert(kev.data == 0);
122 		close(kq);
123 		break;
124 	default:
125 		abort();
126 	}
127 
128 	os_channel_destroy(channel);
129 
130 	error = pthread_join(thread, NULL);
131 	SKTC_ASSERT_ERR(error == 0);
132 
133 	return 0;
134 }
135 
136 static int
skt_shutdown2_select_main(int argc,char * argv[])137 skt_shutdown2_select_main(int argc, char *argv[])
138 {
139 	return skt_shutdown2_common(argc, argv, 0);
140 }
141 
142 static int
skt_shutdown2_poll_main(int argc,char * argv[])143 skt_shutdown2_poll_main(int argc, char *argv[])
144 {
145 	return skt_shutdown2_common(argc, argv, 1);
146 }
147 
148 static int
skt_shutdown2_kqueue_main(int argc,char * argv[])149 skt_shutdown2_kqueue_main(int argc, char *argv[])
150 {
151 	return skt_shutdown2_common(argc, argv, 2);
152 }
153 
154 struct skywalk_test skt_shutdown2us = {
155 	"shutdown2us", "shuts down channel on upipe while in select",
156 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
157 	skt_shutdown2_select_main, SKTC_GENERIC_UPIPE_ARGV,
158 	sktc_generic_upipe_nexus_init, sktc_cleanup_nexus,
159 };
160 
161 struct skywalk_test skt_shutdown2ks = {
162 	"shutdown2ks", "shuts down channel on kpipe while in select",
163 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_KERNEL_PIPE | SK_FEATURE_NEXUS_KERNEL_PIPE_LOOPBACK,
164 	skt_shutdown2_select_main, SKTC_GENERIC_KPIPE_ARGV,
165 	sktc_generic_kpipe_init, sktc_generic_kpipe_fini,
166 };
167 
168 struct skywalk_test skt_shutdown2up = {
169 	"shutdown2up", "shuts down channel on upipe while in poll",
170 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
171 	skt_shutdown2_poll_main, SKTC_GENERIC_UPIPE_ARGV,
172 	sktc_generic_upipe_nexus_init, sktc_cleanup_nexus,
173 };
174 
175 struct skywalk_test skt_shutdown2kp = {
176 	"shutdown2kp", "shuts down channel on kpipe while in poll",
177 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_KERNEL_PIPE | SK_FEATURE_NEXUS_KERNEL_PIPE_LOOPBACK,
178 	skt_shutdown2_poll_main, SKTC_GENERIC_KPIPE_ARGV,
179 	sktc_generic_kpipe_init, sktc_generic_kpipe_fini,
180 };
181 
182 struct skywalk_test skt_shutdown2uk = {
183 	"shutdown2uk", "shuts down channel on upipe while in kqueue",
184 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
185 	skt_shutdown2_kqueue_main, SKTC_GENERIC_UPIPE_ARGV,
186 	sktc_generic_upipe_nexus_init, sktc_cleanup_nexus,
187 };
188 
189 struct skywalk_test skt_shutdown2kk = {
190 	"shutdown2kk", "shuts down channel on kpipe while in kqueue",
191 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_KERNEL_PIPE | SK_FEATURE_NEXUS_KERNEL_PIPE_LOOPBACK,
192 	skt_shutdown2_kqueue_main, SKTC_GENERIC_KPIPE_ARGV,
193 	sktc_generic_kpipe_init, sktc_generic_kpipe_fini,
194 };
195