]>
Commit | Line | Data |
---|---|---|
b0d623f7 A |
1 | /* |
2 | * tests.c | |
3 | * xnu_quick_test | |
4 | * | |
5 | * Created by Jerry Cottingham on 3/25/05. | |
6 | * Copyright 2005 Apple Computer Inc. All rights reserved. | |
7 | * | |
8 | */ | |
9 | ||
10 | #include "tests.h" | |
11 | #include <pthread.h> | |
12 | #include <assert.h> | |
13 | #include <sys/event.h> /* for kqueue tests */ | |
14 | #include <sys/sysctl.h> /* for determining hw */ | |
15 | #include <mach/mach.h> | |
16 | #include <AvailabilityMacros.h> /* for determination of Mac OS X version (tiger, leopard, etc.) */ | |
17 | #include <libkern/OSByteOrder.h> /* for OSSwap32() */ | |
18 | ||
19 | extern char g_target_path[ PATH_MAX ]; | |
20 | extern int g_skip_setuid_tests; | |
b0d623f7 A |
21 | |
22 | int msg_count = 14; | |
23 | int last_msg_seen = 0; | |
24 | pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER; | |
25 | pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; | |
26 | ||
27 | ||
28 | static kern_return_t | |
29 | kmsg_send(mach_port_t remote_port, int index) | |
30 | { | |
31 | int msgh_id = 1000 + index; | |
32 | kern_return_t my_kr; | |
33 | mach_msg_header_t * my_kmsg = NULL; | |
34 | mach_msg_size_t size = sizeof(mach_msg_header_t) + sizeof(int)*index; | |
35 | ||
36 | my_kr = vm_allocate( mach_task_self(), | |
37 | (vm_address_t *)&my_kmsg, | |
38 | size, | |
39 | VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | TRUE ); | |
40 | if (my_kr != KERN_SUCCESS) | |
41 | return my_kr; | |
fe8ab488 A |
42 | my_kmsg->msgh_bits = |
43 | MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0); | |
b0d623f7 A |
44 | my_kmsg->msgh_size = size; |
45 | my_kmsg->msgh_remote_port = remote_port; | |
46 | my_kmsg->msgh_local_port = MACH_PORT_NULL; | |
fe8ab488 | 47 | my_kmsg->msgh_voucher_port = MACH_PORT_NULL; |
b0d623f7 A |
48 | my_kmsg->msgh_id = msgh_id; |
49 | my_kr = mach_msg( my_kmsg, | |
50 | MACH_SEND_MSG | MACH_MSG_OPTION_NONE, | |
51 | size, | |
52 | 0, /* receive size */ | |
53 | MACH_PORT_NULL, | |
54 | MACH_MSG_TIMEOUT_NONE, | |
55 | MACH_PORT_NULL ); | |
56 | vm_deallocate( mach_task_self(), (vm_address_t)my_kmsg, size ); | |
57 | return my_kr; | |
58 | } | |
59 | ||
60 | static kern_return_t | |
61 | kmsg_recv(mach_port_t portset, mach_port_t port, int * msgh_id_return) | |
62 | { | |
63 | kern_return_t my_kr; | |
64 | mach_msg_header_t * my_kmsg = NULL; | |
65 | ||
66 | my_kr = vm_allocate( mach_task_self(), | |
67 | (vm_address_t *)&my_kmsg, | |
68 | PAGE_SIZE, | |
69 | VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | TRUE ); | |
70 | if (my_kr != KERN_SUCCESS) | |
71 | return my_kr; | |
72 | my_kr = mach_msg( my_kmsg, | |
73 | MACH_RCV_MSG | MACH_MSG_OPTION_NONE, | |
74 | 0, /* send size */ | |
75 | PAGE_SIZE, /* receive size */ | |
76 | port, | |
77 | MACH_MSG_TIMEOUT_NONE, | |
78 | MACH_PORT_NULL ); | |
79 | if ( my_kr == KERN_SUCCESS && | |
80 | msgh_id_return != NULL ) | |
81 | *msgh_id_return = my_kmsg->msgh_id; | |
82 | vm_deallocate( mach_task_self(), (vm_address_t)my_kmsg, PAGE_SIZE ); | |
83 | return my_kr; | |
84 | } | |
85 | ||
86 | static void * | |
87 | kmsg_consumer_thread(void * arg) | |
88 | { | |
b0d623f7 A |
89 | int my_kqueue = *(int *)arg; |
90 | int my_err; | |
91 | kern_return_t my_kr; | |
92 | struct kevent my_keventv[3]; | |
93 | int msgid; | |
94 | ||
95 | EV_SET( &my_keventv[0], 0, 0, 0, 0, 0, 0 ); | |
96 | while ( !(my_keventv[0].filter == EVFILT_USER && | |
97 | my_keventv[0].ident == 0)) { | |
98 | /* keep getting events */ | |
99 | my_err = kevent( my_kqueue, NULL, 0, my_keventv, 1, NULL ); | |
100 | if ( my_err == -1 ) { | |
101 | printf( "kevent call from consumer thread failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
102 | return (void *)-1; | |
103 | } | |
104 | if ( my_err == 0 ) { | |
105 | printf( "kevent call from consumer thread did not return any events when it should have \n" ); | |
106 | return (void *)-1; | |
107 | } | |
108 | if ( my_keventv[0].filter == EVFILT_MACHPORT ) { | |
109 | if ( my_keventv[0].data == 0 ) { | |
110 | printf( "kevent call to get machport event returned 0 msg_size \n" ); | |
111 | return (void *)-1; | |
112 | } | |
113 | my_kr = kmsg_recv( my_keventv[0].ident, my_keventv[0].data, &msgid ); | |
114 | if ( my_kr != KERN_SUCCESS ) { | |
115 | printf( "kmsg_recv failed with error %d - %s \n", my_kr, mach_error_string(my_kr) ); | |
116 | return (void *)-1; | |
117 | } | |
118 | my_keventv[0].flags = EV_ENABLE; | |
119 | my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL ); | |
120 | if ( my_err == -1 ) { | |
121 | printf( "kevent call to re-enable machport events failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
122 | return (void *)-1; | |
123 | } | |
124 | if (msgid == 1000 + msg_count) { | |
125 | pthread_mutex_lock(&my_mutex); | |
126 | last_msg_seen = 1; | |
127 | pthread_cond_signal(&my_cond); | |
128 | pthread_mutex_unlock(&my_mutex); | |
129 | } | |
130 | } | |
131 | } | |
132 | return (void *)0; | |
b0d623f7 A |
133 | } |
134 | ||
135 | /* ************************************************************************************************************** | |
136 | * Test kevent, kqueue system calls. | |
137 | * ************************************************************************************************************** | |
138 | */ | |
139 | int kqueue_tests( void * the_argp ) | |
140 | { | |
141 | int my_err, my_status; | |
6d2010ae | 142 | void *my_pthread_join_status; |
b0d623f7 A |
143 | int my_kqueue = -1; |
144 | int my_kqueue64 = -1; | |
145 | int my_fd = -1; | |
146 | char * my_pathp = NULL; | |
147 | pid_t my_pid, my_wait_pid; | |
148 | size_t my_count, my_index; | |
149 | int my_sockets[ 2 ] = {-1, -1}; | |
150 | struct kevent my_keventv[3]; | |
b0d623f7 | 151 | struct kevent64_s my_kevent64; |
b0d623f7 A |
152 | struct timespec my_timeout; |
153 | char my_buffer[ 16 ]; | |
154 | kern_return_t kr; | |
155 | ||
156 | kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE); | |
157 | if(kr != KERN_SUCCESS){ | |
158 | printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
159 | goto test_failed_exit; | |
160 | } | |
161 | ||
162 | *my_pathp = 0x00; | |
163 | strcat( my_pathp, &g_target_path[0] ); | |
164 | strcat( my_pathp, "/" ); | |
165 | ||
166 | /* create a test file */ | |
167 | my_err = create_random_name( my_pathp, 1 ); | |
168 | if ( my_err != 0 ) { | |
169 | goto test_failed_exit; | |
170 | } | |
171 | ||
172 | my_fd = open( my_pathp, O_RDWR, 0 ); | |
173 | if ( my_fd == -1 ) { | |
174 | printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
175 | goto test_failed_exit; | |
176 | } | |
177 | ||
178 | my_err = socketpair( AF_UNIX, SOCK_STREAM, 0, &my_sockets[0] ); | |
179 | if ( my_err == -1 ) { | |
180 | printf( "socketpair failed with errno %d - %s \n", errno, strerror( errno ) ); | |
181 | goto test_failed_exit; | |
182 | } | |
183 | ||
184 | /* fork here and use pipe to communicate */ | |
185 | my_pid = fork( ); | |
186 | if ( my_pid == -1 ) { | |
187 | printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) ); | |
188 | goto test_failed_exit; | |
189 | } | |
190 | else if ( my_pid == 0 ) { | |
191 | /* | |
192 | * child process - tell parent we are ready to go. | |
193 | */ | |
194 | my_count = write( my_sockets[1], "r", 1 ); | |
195 | if ( my_count == -1 ) { | |
196 | printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
197 | exit( -1 ); | |
198 | } | |
199 | ||
200 | my_count = read( my_sockets[1], &my_buffer[0], 1 ); | |
201 | if ( my_count == -1 ) { | |
202 | printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
203 | exit( -1 ); | |
204 | } | |
205 | if ( my_buffer[0] != 'g' ) { | |
206 | printf( "read call on socket failed to get \"all done\" message \n" ); | |
207 | exit( -1 ); | |
208 | } | |
209 | ||
210 | /* now do some work that will trigger events our parent will track */ | |
211 | my_count = write( my_fd, "11111111", 8 ); | |
212 | if ( my_count == -1 ) { | |
213 | printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
214 | exit( -1 ); | |
215 | } | |
216 | ||
217 | my_err = unlink( my_pathp ); | |
218 | if ( my_err == -1 ) { | |
219 | printf( "unlink failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
220 | exit( -1 ); | |
221 | } | |
222 | ||
223 | /* wait for parent to tell us to exit */ | |
224 | my_count = read( my_sockets[1], &my_buffer[0], 1 ); | |
225 | if ( my_count == -1 ) { | |
226 | printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
227 | exit( -1 ); | |
228 | } | |
229 | if ( my_buffer[0] != 'e' ) { | |
230 | printf( "read call on socket failed to get \"all done\" message \n" ); | |
231 | exit( -1 ); | |
232 | } | |
233 | exit(0); | |
234 | } | |
235 | ||
236 | /* parent process - wait for child to spin up */ | |
237 | my_count = read( my_sockets[0], &my_buffer[0], sizeof(my_buffer) ); | |
238 | if ( my_count == -1 ) { | |
239 | printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
240 | goto test_failed_exit; | |
241 | } | |
242 | if ( my_buffer[0] != 'r' ) { | |
243 | printf( "read call on socket failed to get \"ready to go message\" \n" ); | |
244 | goto test_failed_exit; | |
245 | } | |
246 | ||
247 | /* set up a kqueue and register for some events */ | |
248 | my_kqueue = kqueue( ); | |
249 | if ( my_kqueue == -1 ) { | |
250 | printf( "kqueue call failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
251 | goto test_failed_exit; | |
252 | } | |
253 | ||
254 | /* look for our test file to get unlinked or written to */ | |
255 | EV_SET( &my_keventv[0], my_fd, EVFILT_VNODE, (EV_ADD | EV_CLEAR), (NOTE_DELETE | NOTE_WRITE), 0, 0 ); | |
256 | /* also keep an eye on our child process while we're at it */ | |
257 | EV_SET( &my_keventv[1], my_pid, EVFILT_PROC, (EV_ADD | EV_ONESHOT), NOTE_EXIT, 0, 0 ); | |
258 | ||
259 | my_timeout.tv_sec = 0; | |
260 | my_timeout.tv_nsec = 0; | |
261 | my_err = kevent( my_kqueue, my_keventv, 2, NULL, 0, &my_timeout); | |
262 | if ( my_err == -1 ) { | |
263 | printf( "kevent call to register events failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
264 | goto test_failed_exit; | |
265 | } | |
266 | ||
6d2010ae A |
267 | /* use kevent64 to test EVFILT_PROC */ |
268 | EV_SET64( &my_kevent64, my_pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, 0, 0, 0 ); | |
269 | my_err = kevent64( my_kqueue, &my_kevent64, 1, NULL, 0, 0, 0); | |
270 | if ( my_err != -1 && errno != EINVAL ) { | |
271 | printf( "kevent64 call should fail with kqueue used for kevent() - %d\n", my_err); | |
272 | goto test_failed_exit; | |
273 | } | |
b0d623f7 | 274 | |
6d2010ae A |
275 | my_kqueue64 = kqueue(); |
276 | EV_SET64( &my_kevent64, my_pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, 0, 0, 0 ); | |
277 | my_err = kevent64( my_kqueue64, &my_kevent64, 1, NULL, 0, 0, 0); | |
278 | if ( my_err == -1 ) { | |
279 | printf( "kevent64 call to get proc exit failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
280 | goto test_failed_exit; | |
b0d623f7 | 281 | } |
b0d623f7 A |
282 | |
283 | /* tell child to get to work */ | |
284 | my_count = write( my_sockets[0], "g", 1 ); | |
285 | if ( my_count == -1 ) { | |
286 | printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
287 | goto test_failed_exit; | |
288 | } | |
289 | ||
290 | /* go get vnode events */ | |
291 | EV_SET( &my_keventv[0], my_fd, EVFILT_VNODE, (EV_CLEAR), 0, 0, 0 ); | |
292 | my_err = kevent( my_kqueue, NULL, 0, my_keventv, 1, NULL ); | |
293 | if ( my_err == -1 ) { | |
294 | printf( "kevent call to get vnode events failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
295 | goto test_failed_exit; | |
296 | } | |
297 | if ( my_err == 0 ) { | |
298 | printf( "kevent call to get vnode events did not return any when it should have \n" ); | |
299 | goto test_failed_exit; | |
300 | } | |
301 | if ( (my_keventv[0].fflags & (NOTE_DELETE | NOTE_WRITE)) == 0 ) { | |
302 | printf( "kevent call to get vnode events did not return NOTE_DELETE or NOTE_WRITE \n" ); | |
303 | printf( "fflags 0x%02X \n", my_keventv[0].fflags ); | |
304 | goto test_failed_exit; | |
305 | } | |
306 | ||
307 | /* tell child to exit */ | |
308 | my_count = write( my_sockets[0], "e", 1 ); | |
309 | if ( my_count == -1 ) { | |
310 | printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) ); | |
311 | goto test_failed_exit; | |
312 | } | |
313 | ||
314 | /* look for child exit notification after unregistering for vnode events */ | |
315 | EV_SET( &my_keventv[0], my_fd, EVFILT_VNODE, EV_DELETE, 0, 0, 0 ); | |
316 | my_err = kevent( my_kqueue, my_keventv, 1, my_keventv, 1, NULL ); | |
317 | if ( my_err == -1 ) { | |
318 | printf( "kevent call to get proc exit event failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
319 | goto test_failed_exit; | |
320 | } | |
321 | if ( my_err == 0 ) { | |
322 | printf( "kevent call to get proc exit event did not return any when it should have \n" ); | |
323 | goto test_failed_exit; | |
324 | } | |
325 | if ( my_keventv[0].filter != EVFILT_PROC ) { | |
326 | printf( "kevent call to get proc exit event did not return EVFILT_PROC \n" ); | |
327 | printf( "filter %i \n", my_keventv[0].filter ); | |
328 | goto test_failed_exit; | |
329 | } | |
330 | if ( (my_keventv[0].fflags & NOTE_EXIT) == 0 ) { | |
331 | printf( "kevent call to get proc exit event did not return NOTE_EXIT \n" ); | |
332 | printf( "fflags 0x%02X \n", my_keventv[0].fflags ); | |
333 | goto test_failed_exit; | |
334 | } | |
335 | ||
6d2010ae A |
336 | /* look for child exit notification on the kevent64 kqueue */ |
337 | EV_SET64( &my_kevent64, my_pid, EVFILT_PROC, EV_CLEAR, NOTE_EXIT, 0, 0, 0, 0 ); | |
338 | my_err = kevent64( my_kqueue64, NULL, 0, &my_kevent64, 1, 0, 0); | |
339 | if ( my_err == -1 ) { | |
340 | printf( "kevent64 call to get child exit failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
341 | goto test_failed_exit; | |
342 | } | |
343 | if ( my_err == 0 ) { | |
344 | printf( "kevent64 call to get proc exit event did not return any when it should have \n" ); | |
345 | goto test_failed_exit; | |
346 | } | |
347 | if ( my_kevent64.filter != EVFILT_PROC ) { | |
348 | printf( "kevent64 call to get proc exit event did not return EVFILT_PROC \n" ); | |
349 | printf( "filter %i \n", my_kevent64.filter ); | |
350 | goto test_failed_exit; | |
351 | } | |
352 | if ( (my_kevent64.fflags & NOTE_EXIT) == 0 ) { | |
353 | printf( "kevent64 call to get proc exit event did not return NOTE_EXIT \n" ); | |
354 | printf( "fflags 0x%02X \n", my_kevent64.fflags ); | |
355 | goto test_failed_exit; | |
b0d623f7 A |
356 | } |
357 | ||
358 | my_wait_pid = wait4( my_pid, &my_status, 0, NULL ); | |
359 | if ( my_wait_pid == -1 ) { | |
360 | printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) ); | |
361 | goto test_failed_exit; | |
362 | } | |
363 | ||
364 | /* wait4 should return our child's pid when it exits */ | |
365 | if ( my_wait_pid != my_pid ) { | |
366 | printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid ); | |
367 | goto test_failed_exit; | |
368 | } | |
369 | ||
370 | if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) { | |
371 | printf( "wait4 returned wrong exit status - 0x%02X \n", my_status ); | |
372 | goto test_failed_exit; | |
373 | } | |
374 | ||
375 | /* now try out EVFILT_MACHPORT and EVFILT_USER */ | |
376 | mach_port_t my_pset = MACH_PORT_NULL; | |
377 | mach_port_t my_port = MACH_PORT_NULL; | |
378 | kern_return_t my_kr; | |
379 | ||
380 | my_kr = mach_port_allocate( mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &my_pset ); | |
381 | if ( my_kr != KERN_SUCCESS ) { | |
382 | printf( "mach_port_allocate failed with error %d - %s \n", my_kr, mach_error_string(my_kr) ); | |
383 | goto test_failed_exit; | |
384 | } | |
385 | ||
386 | my_kr = mach_port_allocate( mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &my_port ); | |
387 | if ( my_kr != KERN_SUCCESS ) { | |
388 | printf( "mach_port_allocate failed with error %d - %s \n", my_kr, mach_error_string(my_kr) ); | |
389 | goto test_failed_exit; | |
390 | } | |
391 | ||
392 | /* try to register for events on my_port directly -- this should fail */ | |
393 | EV_SET( &my_keventv[0], my_port, EVFILT_MACHPORT, (EV_ADD | EV_DISPATCH), 0, 0, 0 ); | |
394 | my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL ); | |
395 | if ( my_err != -1 || errno != ENOTSUP ) { | |
396 | printf( "kevent call to register my_port should have failed, but got %s \n", strerror(errno) ); | |
397 | goto test_failed_exit; | |
398 | } | |
399 | ||
400 | /* now register for events on my_pset and user 0 */ | |
401 | EV_SET( &my_keventv[0], my_pset, EVFILT_MACHPORT, (EV_ADD | EV_CLEAR | EV_DISPATCH), 0, 0, 0 ); | |
402 | EV_SET( &my_keventv[1], 0, EVFILT_USER, EV_ADD, 0, 0, 0 ); | |
403 | my_err = kevent( my_kqueue, my_keventv, 2, NULL, 0, NULL ); | |
404 | if ( my_err == -1 ) { | |
405 | printf( "kevent call to register my_pset and user 0 failed with error %d - %s \n", errno, strerror( errno) ); | |
406 | goto test_failed_exit; | |
407 | } | |
408 | ||
409 | pthread_t my_threadv[3]; | |
410 | ||
411 | for (my_index = 0; | |
412 | my_index < 3; | |
413 | my_index++) { | |
414 | my_err = pthread_create( &my_threadv[my_index], NULL, kmsg_consumer_thread, (void *)&my_kqueue ); | |
415 | if ( my_err != 0 ) { | |
416 | printf( "pthread_create failed with error %d - %s \n", my_err, strerror(my_err) ); | |
417 | goto test_failed_exit; | |
418 | } | |
419 | } | |
420 | ||
421 | /* insert my_port into my_pset */ | |
422 | my_kr = mach_port_insert_member( mach_task_self(), my_port, my_pset ); | |
423 | if ( my_kr != KERN_SUCCESS ) { | |
424 | printf( "mach_port_insert_member failed with error %d - %s \n", my_kr, mach_error_string(my_kr) ); | |
425 | goto test_failed_exit; | |
426 | } | |
427 | ||
428 | my_kr = mach_port_insert_right( mach_task_self(), my_port, my_port, MACH_MSG_TYPE_MAKE_SEND ); | |
429 | if ( my_kr != KERN_SUCCESS ) { | |
430 | printf( "mach_port_insert_right failed with error %d - %s \n", my_kr, mach_error_string(my_kr) ); | |
431 | goto test_failed_exit; | |
432 | } | |
433 | ||
434 | /* send some Mach messages */ | |
435 | for (my_index = 1; | |
436 | my_index <= msg_count; | |
437 | my_index++) { | |
438 | my_kr = kmsg_send( my_port, my_index ); | |
439 | if ( my_kr != KERN_SUCCESS ) { | |
440 | printf( "kmsg_send failed with error %d - %s \n", my_kr, mach_error_string(my_kr) ); | |
441 | goto test_failed_exit; | |
442 | } | |
443 | } | |
444 | ||
445 | /* make sure the last message eventually gets processed */ | |
446 | pthread_mutex_lock(&my_mutex); | |
447 | while (last_msg_seen == 0) | |
448 | pthread_cond_wait(&my_cond, &my_mutex); | |
449 | pthread_mutex_unlock(&my_mutex); | |
450 | ||
451 | /* trigger the user 0 event, telling consumer threads to exit */ | |
452 | EV_SET( &my_keventv[0], 0, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0 ); | |
453 | my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL ); | |
454 | if ( my_err == -1 ) { | |
455 | printf( "kevent call to trigger user 0 failed with error %d - %s \n", errno, strerror( errno) ); | |
456 | goto test_failed_exit; | |
457 | } | |
458 | ||
459 | for (my_index = 0; | |
460 | my_index < 3; | |
461 | my_index++) { | |
6d2010ae | 462 | my_err = pthread_join( my_threadv[my_index], &my_pthread_join_status ); |
b0d623f7 A |
463 | if ( my_err != 0 ) { |
464 | printf( "pthread_join failed with error %d - %s \n", my_err, strerror(my_err) ); | |
465 | goto test_failed_exit; | |
466 | } | |
6d2010ae | 467 | if ( my_pthread_join_status != 0 ) { |
b0d623f7 A |
468 | goto test_failed_exit; |
469 | } | |
470 | } | |
471 | ||
472 | /* clear the user 0 event */ | |
473 | EV_SET( &my_keventv[0], 0, EVFILT_USER, EV_CLEAR, 0, 0, 0 ); | |
474 | my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL ); | |
475 | if ( my_err == -1 ) { | |
476 | printf( "kevent call to trigger user 0 failed with error %d - %s \n", errno, strerror( errno) ); | |
477 | goto test_failed_exit; | |
478 | } | |
479 | ||
480 | /* delibrately destroy my_pset while it's still registered for events */ | |
481 | my_kr = mach_port_mod_refs( mach_task_self(), my_pset, MACH_PORT_RIGHT_PORT_SET, -1 ); | |
482 | if ( my_kr != KERN_SUCCESS ) { | |
483 | printf( "mach_port_mod_refs failed with error %d - %s \n", my_kr, mach_error_string(my_kr) ); | |
484 | goto test_failed_exit; | |
485 | } | |
486 | ||
487 | /* look for the event to trigger with a zero msg_size */ | |
488 | my_err = kevent( my_kqueue, NULL, 0, my_keventv, 1, NULL ); | |
489 | if ( my_err == -1 ) { | |
490 | printf( "kevent call to get machport event failed with error %d - \"%s\" \n", errno, strerror( errno) ); | |
491 | goto test_failed_exit; | |
492 | } | |
493 | if ( my_err == 0 ) { | |
494 | printf( "kevent call to get machport event did not return any when it should have \n" ); | |
495 | goto test_failed_exit; | |
496 | } | |
497 | if ( my_keventv[0].filter != EVFILT_MACHPORT ) { | |
498 | printf( "kevent call to get machport event did not return EVFILT_MACHPORT \n" ); | |
499 | printf( "filter %i \n", my_keventv[0].filter ); | |
500 | goto test_failed_exit; | |
501 | } | |
502 | if ( my_keventv[0].data != 0 ) { | |
503 | printf( "kevent call to get machport event did not return 0 msg_size \n" ); | |
504 | printf( "data %ld \n", (long int) my_keventv[0].data ); | |
505 | goto test_failed_exit; | |
506 | } | |
b0d623f7 A |
507 | |
508 | my_err = 0; | |
509 | goto test_passed_exit; | |
510 | ||
511 | test_failed_exit: | |
512 | my_err = -1; | |
513 | ||
514 | test_passed_exit: | |
515 | if ( my_sockets[0] != -1 ) | |
516 | close( my_sockets[0] ); | |
517 | if ( my_sockets[1] != -1 ) | |
518 | close( my_sockets[1] ); | |
519 | if ( my_kqueue != -1 ) | |
520 | close( my_kqueue ); | |
521 | if ( my_kqueue64 != -1 ) | |
522 | close( my_kqueue ); | |
523 | if ( my_fd != -1 ) | |
524 | close( my_fd ); | |
525 | if ( my_pathp != NULL ) { | |
526 | remove( my_pathp ); | |
527 | vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX); | |
528 | } | |
529 | return( my_err ); | |
530 | } |