1 /* $OpenBSD: close_race.c,v 1.2 2006/10/06 13:11:58 kurt Exp $ */
2 /*
3 * Copyright (c) 2006 Kurt Miller <kurt@intricatesoftware.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /*
19 * Test close() racing with other threads using the same file
20 * descriptor.
21 */
22
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <time.h>
27 #include <sys/socket.h>
28 #include "test.h"
29
30 #define ITERATIONS 100
31 #define BUSY_THREADS 10
32
33 static void *
deadlock_detector(void * arg)34 deadlock_detector(void *arg)
35 {
36 sleep(60);
37 PANIC("deadlock detected");
38 }
39
40 static void *
busy_thread(void * arg)41 busy_thread(void *arg)
42 {
43 int fd = *(int *)arg;
44
45 /* loop until error */
46 while(fcntl(fd, F_GETFD, NULL) != -1);
47
48 return ((caddr_t)NULL + errno);
49 }
50
51 int
main(int argc,char * argv[])52 main(int argc, char *argv[])
53 {
54 pthread_t busy_threads[BUSY_THREADS], deadlock_thread;
55 int fd, i, j;
56 void *value_ptr;
57 struct timespec rqtp;
58
59 rqtp.tv_sec = 0;
60 rqtp.tv_nsec = 1000000;
61
62 CHECKr(pthread_create(&deadlock_thread, NULL,
63 deadlock_detector, NULL));
64
65 for (i = 0; i < ITERATIONS; i++) {
66 CHECKe(fd = socket(AF_INET, SOCK_DGRAM, 0));
67 for (j = 0; j < BUSY_THREADS; j++)
68 CHECKr(pthread_create(&busy_threads[j], NULL,
69 busy_thread, (void *)&fd));
70 nanosleep(&rqtp, NULL);
71 CHECKr(close(fd));
72 for (j = 0; j < 5; j++) {
73 CHECKr(pthread_join(busy_threads[j], &value_ptr));
74 ASSERT(value_ptr == (void *)EBADF);
75 }
76 }
77 SUCCEED;
78 }
79