1/* $OpenBSD: blocked_dup2.c,v 1.4 2012/02/20 17:06:11 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, with some of them blocking on data that will never 21 * arrive. 22 */ 23 24#include <pthread.h> 25#include <unistd.h> 26#include <fcntl.h> 27#include <time.h> 28#include <sys/types.h> 29#include <sys/socket.h> 30#include <netinet/in.h> 31#include "test.h" 32 33#define ITERATIONS 100 34#define WAITING_THREADS 5 35 36static void * 37deadlock_detector(void *arg) 38{ 39 sleep(15); 40 PANIC("deadlock detected"); 41} 42 43static void * 44waiting_read(void *arg) 45{ 46 int fd = *(int *)arg; 47 struct sockaddr remote_addr; 48 char readBuf; 49 int n, remote_addr_len = sizeof(struct sockaddr); 50 51 n = recvfrom(fd, &readBuf, 1, 0, &remote_addr, &remote_addr_len); 52 53 if (n == -1) 54 return ((caddr_t)NULL + errno); 55 else 56 return (NULL); 57} 58 59int 60main(int argc, char *argv[]) 61{ 62 pthread_t waiting_threads[WAITING_THREADS]; 63 pthread_t deadlock_thread; 64 struct sockaddr_in addr; 65 int fd, newfd, i, j; 66 void *value_ptr; 67 struct timespec rqtp; 68 69 rqtp.tv_sec = 0; 70 rqtp.tv_nsec = 1000000; 71 72 bzero((char *) &addr, sizeof addr); 73 addr.sin_family = AF_INET; 74 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 75 addr.sin_port = htons(0); 76 77 CHECKr(pthread_create(&deadlock_thread, NULL, 78 deadlock_detector, NULL)); 79 80 CHECKe(fd = socket(AF_INET, SOCK_DGRAM, 0)); 81 CHECKr(bind(fd, (struct sockaddr *)&addr, sizeof(addr))); 82 83 CHECKe(newfd = socket(AF_INET, SOCK_DGRAM, 0)); 84 CHECKr(bind(newfd, (struct sockaddr *)&addr, sizeof(addr))); 85 86 for (i = 0; i < ITERATIONS; i++) { 87 for (j = 0; j < WAITING_THREADS; j++) 88 CHECKr(pthread_create(&waiting_threads[j], NULL, 89 waiting_read, (void *)&newfd)); 90 nanosleep(&rqtp, NULL); 91 CHECKe(dup2(fd, newfd)); 92 for (j = 0; j < WAITING_THREADS; j++) { 93 CHECKr(pthread_join(waiting_threads[j], &value_ptr)); 94 ASSERT(value_ptr == (void *)EBADF); 95 } 96 } 97 SUCCEED; 98} 99