OSDN Git Service

initial commit
[openbsd-octeon/openbsd-octeon.git] / src / regress / lib / libpthread / blocked_close / blocked_close.c
1 /*      $OpenBSD: blocked_close.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, with some of them blocking on data that will never
21  * arrive.
22  */
23
24 #include <pthread.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <time.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include "test.h"
32
33 #define ITERATIONS      100
34 #define BUSY_THREADS    5
35 #define WAITING_THREADS 5
36
37 static void *
38 deadlock_detector(void *arg)
39 {
40         sleep(60);
41         PANIC("deadlock detected");
42 }
43
44 static void *
45 waiting_read(void *arg)
46 {
47         int fd = *(int *)arg;
48         struct sockaddr remote_addr;
49         char readBuf;
50         int n, remote_addr_len = sizeof(struct sockaddr);
51
52         n = recvfrom(fd, &readBuf, 1, 0, &remote_addr, &remote_addr_len);
53
54         if (n == -1)
55                 return ((caddr_t)NULL + errno);
56         else
57                 return (NULL);
58 }
59
60 static void *
61 busy_thread(void *arg)
62 {
63         int fd = *(int *)arg;
64
65         /* loop until error */
66         while(fcntl(fd, F_GETFD, NULL) != -1);
67
68         return ((caddr_t)NULL + errno);
69 }
70
71 int
72 main(int argc, char *argv[])
73 {
74         pthread_t busy_threads[BUSY_THREADS];
75         pthread_t waiting_threads[WAITING_THREADS];
76         pthread_t deadlock_thread;
77         struct sockaddr_in addr;
78         int fd, i, j;
79         void *value_ptr;
80         struct timespec rqtp;
81
82         rqtp.tv_sec = 0;
83         rqtp.tv_nsec = 1000000;
84
85         bzero((char *) &addr, sizeof addr);
86         addr.sin_family = AF_INET;
87         addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
88         addr.sin_port = htons(0);
89
90         CHECKr(pthread_create(&deadlock_thread, NULL,
91             deadlock_detector, NULL));
92
93         for (i = 0; i < ITERATIONS; i++) {
94                 CHECKe(fd = socket(AF_INET, SOCK_DGRAM, 0));
95                 CHECKr(bind(fd, (struct sockaddr *)&addr, sizeof(addr)));
96                 for (j = 0; j < BUSY_THREADS; j++)
97                         CHECKr(pthread_create(&busy_threads[j], NULL,
98                             busy_thread, (void *)&fd));
99                 for (j = 0; j < WAITING_THREADS; j++)
100                         CHECKr(pthread_create(&waiting_threads[j], NULL,
101                             waiting_read, (void *)&fd));
102                 nanosleep(&rqtp, NULL);
103                 CHECKr(close(fd));
104                 for (j = 0; j < BUSY_THREADS; j++) {
105                         CHECKr(pthread_join(busy_threads[j], &value_ptr));
106                         ASSERT(value_ptr == (void *)EBADF);
107                 }
108                 for (j = 0; j < WAITING_THREADS; j++) {
109                         CHECKr(pthread_join(waiting_threads[j], &value_ptr));
110                         ASSERT(value_ptr == (void *)EBADF);
111                 }
112         }       
113         SUCCEED;
114 }