xref: /openbsd-src/regress/lib/libpthread/dup2_race/dup2_race.c (revision d53f110ce7d6e28ecd28b78c7387a5717747990b)
1*d53f110cSkurt /*	$OpenBSD: dup2_race.c,v 1.3 2006/10/06 13:11:58 kurt Exp $	*/
221982d47Skurt /*
321982d47Skurt  * Copyright (c) 2006 Kurt Miller <kurt@intricatesoftware.com>
421982d47Skurt  *
521982d47Skurt  * Permission to use, copy, modify, and distribute this software for any
621982d47Skurt  * purpose with or without fee is hereby granted, provided that the above
721982d47Skurt  * copyright notice and this permission notice appear in all copies.
821982d47Skurt  *
921982d47Skurt  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1021982d47Skurt  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1121982d47Skurt  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1221982d47Skurt  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1321982d47Skurt  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1421982d47Skurt  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1521982d47Skurt  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1621982d47Skurt  */
1721982d47Skurt 
1821982d47Skurt /*
1921982d47Skurt  * Test dup2() racing with other threads using the same file
2021982d47Skurt  * descriptor.
2121982d47Skurt  */
2221982d47Skurt 
2321982d47Skurt #include <pthread.h>
2421982d47Skurt #include <unistd.h>
2521982d47Skurt #include <fcntl.h>
2621982d47Skurt #include <time.h>
2721982d47Skurt #include <sys/socket.h>
2821982d47Skurt #include "test.h"
2921982d47Skurt 
3021982d47Skurt #define ITERATIONS	100
3121982d47Skurt #define BUSY_THREADS	10
3221982d47Skurt 
3321982d47Skurt static void *
deadlock_detector(void * arg)3421982d47Skurt deadlock_detector(void *arg)
3521982d47Skurt {
3621982d47Skurt 	sleep(60);
3721982d47Skurt 	PANIC("deadlock detected");
3821982d47Skurt }
3921982d47Skurt 
4021982d47Skurt static void *
busy_thread(void * arg)4121982d47Skurt busy_thread(void *arg)
4221982d47Skurt {
43*d53f110cSkurt 	int fd = *(int *)arg;
4421982d47Skurt 
4521982d47Skurt 	/* loop until error */
4621982d47Skurt 	while(fcntl(fd, F_GETFD, NULL) != -1);
4721982d47Skurt 
48*d53f110cSkurt 	return ((caddr_t)NULL + errno);
4921982d47Skurt }
5021982d47Skurt 
5121982d47Skurt int
main(int argc,char * argv[])5221982d47Skurt main(int argc, char *argv[])
5321982d47Skurt {
5421982d47Skurt 	pthread_t busy_threads[BUSY_THREADS], deadlock_thread;
5521982d47Skurt 	int fd, newfd, i, j;
5621982d47Skurt 	void *value_ptr;
5721982d47Skurt 	struct timespec rqtp;
5821982d47Skurt 
5921982d47Skurt 	rqtp.tv_sec = 0;
6021982d47Skurt 	rqtp.tv_nsec = 1000000;
6121982d47Skurt 
6221982d47Skurt 	CHECKr(pthread_create(&deadlock_thread, NULL,
6321982d47Skurt 	    deadlock_detector, NULL));
6421982d47Skurt 
6521982d47Skurt 	CHECKe(fd = socket(AF_INET, SOCK_DGRAM, 0));
6621982d47Skurt 
6721982d47Skurt 	for (i = 0; i < 100; i++) {
6821982d47Skurt 		CHECKe(newfd = socket(AF_INET, SOCK_DGRAM, 0));
6921982d47Skurt 		for (j = 0; j < BUSY_THREADS; j++)
7021982d47Skurt 			CHECKr(pthread_create(&busy_threads[j], NULL,
71*d53f110cSkurt 			    busy_thread, (void *)&newfd));
7221982d47Skurt 		nanosleep(&rqtp, NULL);
73ffa3ffc0Skurt 		CHECKe(dup2(fd, newfd));
7421982d47Skurt 		for (j = 0; j < BUSY_THREADS; j++) {
7521982d47Skurt 			CHECKr(pthread_join(busy_threads[j], &value_ptr));
7621982d47Skurt 			ASSERT(value_ptr == (void *)EBADF);
7721982d47Skurt 		}
7821982d47Skurt 		CHECKe(close(newfd));
7921982d47Skurt 	}
8021982d47Skurt 	SUCCEED;
8121982d47Skurt }
82