1 /* $OpenBSD: dup2_race.c,v 1.3 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 dup2() racing with other threads using the same file 20 * descriptor. 21 */ 22 23 #include <pthread.h> 24 #include <unistd.h> 25 #include <fcntl.h> 26 #include <time.h> 27 #include <sys/socket.h> 28 #include "test.h" 29 30 #define ITERATIONS 100 31 #define BUSY_THREADS 10 32 33 static void * 34 deadlock_detector(void *arg) 35 { 36 sleep(60); 37 PANIC("deadlock detected"); 38 } 39 40 static void * 41 busy_thread(void *arg) 42 { 43 int fd = *(int *)arg; 44 45 /* loop until error */ 46 while(fcntl(fd, F_GETFD, NULL) != -1); 47 48 return ((caddr_t)NULL + errno); 49 } 50 51 int 52 main(int argc, char *argv[]) 53 { 54 pthread_t busy_threads[BUSY_THREADS], deadlock_thread; 55 int fd, newfd, i, j; 56 void *value_ptr; 57 struct timespec rqtp; 58 59 rqtp.tv_sec = 0; 60 rqtp.tv_nsec = 1000000; 61 62 CHECKr(pthread_create(&deadlock_thread, NULL, 63 deadlock_detector, NULL)); 64 65 CHECKe(fd = socket(AF_INET, SOCK_DGRAM, 0)); 66 67 for (i = 0; i < 100; i++) { 68 CHECKe(newfd = socket(AF_INET, SOCK_DGRAM, 0)); 69 for (j = 0; j < BUSY_THREADS; j++) 70 CHECKr(pthread_create(&busy_threads[j], NULL, 71 busy_thread, (void *)&newfd)); 72 nanosleep(&rqtp, NULL); 73 CHECKe(dup2(fd, newfd)); 74 for (j = 0; j < BUSY_THREADS; j++) { 75 CHECKr(pthread_join(busy_threads[j], &value_ptr)); 76 ASSERT(value_ptr == (void *)EBADF); 77 } 78 CHECKe(close(newfd)); 79 } 80 SUCCEED; 81 } 82