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