xref: /openbsd-src/regress/lib/libpthread/blocked_dup2/blocked_dup2.c (revision 8e3d492bc4902d8a4efdc3b97b471d43e518e923)
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