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