1*d53f110cSkurt /* $OpenBSD: blocked_dup2.c,v 1.3 2006/10/06 13:11:58 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 BUSY_THREADS 5 35a98c3995Skurt #define WAITING_THREADS 5 36a98c3995Skurt 37a98c3995Skurt static void * 38a98c3995Skurt deadlock_detector(void *arg) 39a98c3995Skurt { 40a98c3995Skurt sleep(60); 41a98c3995Skurt PANIC("deadlock detected"); 42a98c3995Skurt } 43a98c3995Skurt 44a98c3995Skurt static void * 45a98c3995Skurt waiting_read(void *arg) 46a98c3995Skurt { 47*d53f110cSkurt int fd = *(int *)arg; 48a98c3995Skurt struct sockaddr remote_addr; 49a98c3995Skurt char readBuf; 50a98c3995Skurt int n, remote_addr_len = sizeof(struct sockaddr); 51a98c3995Skurt 52a98c3995Skurt n = recvfrom(fd, &readBuf, 1, 0, &remote_addr, &remote_addr_len); 53a98c3995Skurt 54a98c3995Skurt if (n == -1) 55*d53f110cSkurt return ((caddr_t)NULL + errno); 56a98c3995Skurt else 57*d53f110cSkurt return (NULL); 58a98c3995Skurt } 59a98c3995Skurt 60a98c3995Skurt static void * 61a98c3995Skurt busy_thread(void *arg) 62a98c3995Skurt { 63*d53f110cSkurt int fd = *(int *)arg; 64a98c3995Skurt 65a98c3995Skurt /* loop until error */ 66a98c3995Skurt while(fcntl(fd, F_GETFD, NULL) != -1); 67a98c3995Skurt 68*d53f110cSkurt return ((caddr_t)NULL + errno); 69a98c3995Skurt } 70a98c3995Skurt 71a98c3995Skurt int 72a98c3995Skurt main(int argc, char *argv[]) 73a98c3995Skurt { 74a98c3995Skurt pthread_t busy_threads[BUSY_THREADS]; 75a98c3995Skurt pthread_t waiting_threads[WAITING_THREADS]; 76a98c3995Skurt pthread_t deadlock_thread; 77a98c3995Skurt struct sockaddr_in addr; 78a98c3995Skurt int fd, newfd, i, j; 79a98c3995Skurt void *value_ptr; 80a98c3995Skurt struct timespec rqtp; 81a98c3995Skurt 82a98c3995Skurt rqtp.tv_sec = 0; 83a98c3995Skurt rqtp.tv_nsec = 1000000; 84a98c3995Skurt 85a98c3995Skurt bzero((char *) &addr, sizeof addr); 86a98c3995Skurt addr.sin_family = AF_INET; 87a98c3995Skurt addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 88a98c3995Skurt addr.sin_port = htons(0); 89a98c3995Skurt 90a98c3995Skurt CHECKr(pthread_create(&deadlock_thread, NULL, 91a98c3995Skurt deadlock_detector, NULL)); 92a98c3995Skurt 93a98c3995Skurt CHECKe(fd = socket(AF_INET, SOCK_DGRAM, 0)); 94a98c3995Skurt CHECKr(bind(fd, (struct sockaddr *)&addr, sizeof(addr))); 95a98c3995Skurt 96a98c3995Skurt CHECKe(newfd = socket(AF_INET, SOCK_DGRAM, 0)); 97a98c3995Skurt CHECKr(bind(newfd, (struct sockaddr *)&addr, sizeof(addr))); 98a98c3995Skurt 99a98c3995Skurt for (i = 0; i < ITERATIONS; i++) { 100a98c3995Skurt for (j = 0; j < BUSY_THREADS; j++) 101a98c3995Skurt CHECKr(pthread_create(&busy_threads[j], NULL, 102*d53f110cSkurt busy_thread, (void *)&newfd)); 103a98c3995Skurt for (j = 0; j < WAITING_THREADS; j++) 104a98c3995Skurt CHECKr(pthread_create(&waiting_threads[j], NULL, 105*d53f110cSkurt waiting_read, (void *)&newfd)); 106a98c3995Skurt nanosleep(&rqtp, NULL); 107ffa3ffc0Skurt CHECKe(dup2(fd, newfd)); 108a98c3995Skurt for (j = 0; j < BUSY_THREADS; j++) { 109a98c3995Skurt CHECKr(pthread_join(busy_threads[j], &value_ptr)); 110a98c3995Skurt ASSERT(value_ptr == (void *)EBADF); 111a98c3995Skurt } 112a98c3995Skurt for (j = 0; j < WAITING_THREADS; j++) { 113a98c3995Skurt CHECKr(pthread_join(waiting_threads[j], &value_ptr)); 114a98c3995Skurt ASSERT(value_ptr == (void *)EBADF); 115a98c3995Skurt } 116a98c3995Skurt } 117a98c3995Skurt SUCCEED; 118a98c3995Skurt } 119