1*8e3d492bSkurt /* $OpenBSD: blocked_dup2.c,v 1.4 2012/02/20 17:06:11 kurt Exp $ */
2a98c3995Skurt /*
3a98c3995Skurt * Copyright (c) 2006 Kurt Miller <kurt@intricatesoftware.com>
4a98c3995Skurt *
5a98c3995Skurt * Permission to use, copy, modify, and distribute this software for any
6a98c3995Skurt * purpose with or without fee is hereby granted, provided that the above
7a98c3995Skurt * copyright notice and this permission notice appear in all copies.
8a98c3995Skurt *
9a98c3995Skurt * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10a98c3995Skurt * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11a98c3995Skurt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12a98c3995Skurt * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13a98c3995Skurt * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14a98c3995Skurt * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15a98c3995Skurt * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16a98c3995Skurt */
17a98c3995Skurt
18a98c3995Skurt /*
19a98c3995Skurt * Test dup2() racing with other threads using the same file
20a98c3995Skurt * descriptor, with some of them blocking on data that will never
21a98c3995Skurt * arrive.
22a98c3995Skurt */
23a98c3995Skurt
24a98c3995Skurt #include <pthread.h>
25a98c3995Skurt #include <unistd.h>
26a98c3995Skurt #include <fcntl.h>
27a98c3995Skurt #include <time.h>
28a98c3995Skurt #include <sys/types.h>
29a98c3995Skurt #include <sys/socket.h>
30a98c3995Skurt #include <netinet/in.h>
31a98c3995Skurt #include "test.h"
32a98c3995Skurt
33a98c3995Skurt #define ITERATIONS 100
34a98c3995Skurt #define WAITING_THREADS 5
35a98c3995Skurt
36a98c3995Skurt static void *
deadlock_detector(void * arg)37a98c3995Skurt deadlock_detector(void *arg)
38a98c3995Skurt {
39*8e3d492bSkurt sleep(15);
40a98c3995Skurt PANIC("deadlock detected");
41a98c3995Skurt }
42a98c3995Skurt
43a98c3995Skurt static void *
waiting_read(void * arg)44a98c3995Skurt waiting_read(void *arg)
45a98c3995Skurt {
46d53f110cSkurt int fd = *(int *)arg;
47a98c3995Skurt struct sockaddr remote_addr;
48a98c3995Skurt char readBuf;
49a98c3995Skurt int n, remote_addr_len = sizeof(struct sockaddr);
50a98c3995Skurt
51a98c3995Skurt n = recvfrom(fd, &readBuf, 1, 0, &remote_addr, &remote_addr_len);
52a98c3995Skurt
53a98c3995Skurt if (n == -1)
54d53f110cSkurt return ((caddr_t)NULL + errno);
55a98c3995Skurt else
56d53f110cSkurt return (NULL);
57a98c3995Skurt }
58a98c3995Skurt
59a98c3995Skurt int
main(int argc,char * argv[])60a98c3995Skurt main(int argc, char *argv[])
61a98c3995Skurt {
62a98c3995Skurt pthread_t waiting_threads[WAITING_THREADS];
63a98c3995Skurt pthread_t deadlock_thread;
64a98c3995Skurt struct sockaddr_in addr;
65a98c3995Skurt int fd, newfd, i, j;
66a98c3995Skurt void *value_ptr;
67a98c3995Skurt struct timespec rqtp;
68a98c3995Skurt
69a98c3995Skurt rqtp.tv_sec = 0;
70a98c3995Skurt rqtp.tv_nsec = 1000000;
71a98c3995Skurt
72a98c3995Skurt bzero((char *) &addr, sizeof addr);
73a98c3995Skurt addr.sin_family = AF_INET;
74a98c3995Skurt addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
75a98c3995Skurt addr.sin_port = htons(0);
76a98c3995Skurt
77a98c3995Skurt CHECKr(pthread_create(&deadlock_thread, NULL,
78a98c3995Skurt deadlock_detector, NULL));
79a98c3995Skurt
80a98c3995Skurt CHECKe(fd = socket(AF_INET, SOCK_DGRAM, 0));
81a98c3995Skurt CHECKr(bind(fd, (struct sockaddr *)&addr, sizeof(addr)));
82a98c3995Skurt
83a98c3995Skurt CHECKe(newfd = socket(AF_INET, SOCK_DGRAM, 0));
84a98c3995Skurt CHECKr(bind(newfd, (struct sockaddr *)&addr, sizeof(addr)));
85a98c3995Skurt
86a98c3995Skurt for (i = 0; i < ITERATIONS; i++) {
87a98c3995Skurt for (j = 0; j < WAITING_THREADS; j++)
88a98c3995Skurt CHECKr(pthread_create(&waiting_threads[j], NULL,
89d53f110cSkurt waiting_read, (void *)&newfd));
90a98c3995Skurt nanosleep(&rqtp, NULL);
91ffa3ffc0Skurt CHECKe(dup2(fd, newfd));
92a98c3995Skurt for (j = 0; j < WAITING_THREADS; j++) {
93a98c3995Skurt CHECKr(pthread_join(waiting_threads[j], &value_ptr));
94a98c3995Skurt ASSERT(value_ptr == (void *)EBADF);
95a98c3995Skurt }
96a98c3995Skurt }
97a98c3995Skurt SUCCEED;
98a98c3995Skurt }
99