1 /* $OpenBSD: socket3.c,v 1.4 2005/10/30 23:59:43 fgsch Exp $ */ 2 /* PUBLIC DOMAIN Oct 2002 <marc@snafu.org> */ 3 4 /* Test blocking/non-blocking mode inheritance on accept */ 5 6 #include <sys/types.h> 7 #include <sys/socket.h> 8 9 #include <netinet/in.h> 10 11 #include <fcntl.h> 12 #include <poll.h> 13 #include <pthread.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 #include "test.h" 18 19 /* 20 * connect to the test port passed in arg, then close the connection 21 * and return. 22 */ 23 static void * 24 sock_connect(void *arg) 25 { 26 struct sockaddr_in sin; 27 int port; 28 int sock; 29 30 SET_NAME("connect"); 31 port = *(int *)arg; 32 CHECKe(sock = socket(AF_INET, SOCK_STREAM, 0)); 33 sin.sin_family = AF_INET; 34 sin.sin_port = htons(port); 35 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 36 CHECKe(connect(sock, (struct sockaddr *)&sin, sizeof sin)); 37 CHECKe(close(sock)); 38 return NULL; 39 } 40 41 /* 42 * listen for a connection, accept it using a non-blocking socket, and 43 * verify that the blocking mode of the socket returned from accept is 44 * also non-blocking 45 */ 46 static void * 47 sock_accept(void *arg) 48 { 49 pthread_t connect_thread; 50 struct pollfd fds; 51 struct sockaddr_in sa; 52 struct sockaddr accept_sa; 53 int accept_fd; 54 int accept_sa_size; 55 int flags; 56 int listen_fd; 57 int port; 58 59 SET_NAME("accept"); 60 61 /* listen for a connection */ 62 63 port = 6543; 64 memset(&sa, 0, sizeof sa); 65 sa.sin_family = AF_INET; 66 sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 67 sa.sin_port = htons(port); 68 CHECKe(listen_fd = socket(AF_INET, SOCK_STREAM, 0)); 69 printf("listen_fd = %d\n", listen_fd); 70 while (1) { 71 if (bind(listen_fd, (struct sockaddr *)&sa, sizeof(sa)) == 0) 72 break; 73 if (errno == EADDRINUSE) { 74 sa.sin_port = htons(++port); 75 continue; 76 } 77 DIE(errno, "bind"); 78 } 79 CHECKe(listen(listen_fd, 2)); 80 81 /* Create another thread to connect to the listening socket. */ 82 CHECKr(pthread_create(&connect_thread, NULL, sock_connect, 83 (void *)&port)); 84 85 /* 86 * Use poll to check for a pending connection as the socket 87 * passed to accept will be in non-blocking mode. 88 */ 89 fds.fd = listen_fd; 90 fds.events = POLLIN; 91 CHECKe(poll(&fds, 1, INFTIM)); 92 93 /* 94 * set non blocking mode on the listening socket and close stdin 95 * (fd 0) so the accept will use fd 0 (needed to test boundary 96 * condition in the pthread accept code). 97 */ 98 flags = fcntl(listen_fd, F_GETFL); 99 CHECKr(fcntl(listen_fd, F_SETFL, flags |= O_NONBLOCK)); 100 CHECKe(close(STDIN_FILENO)); 101 accept_sa_size = sizeof accept_sa; 102 CHECKe(accept_fd = accept(listen_fd, &accept_sa, &accept_sa_size)); 103 /* verify O_NONBLOCK on the accepted fd */ 104 flags = fcntl(accept_fd, F_GETFL); 105 printf("accept_fd = %d, flags = %x\n", accept_fd, flags); 106 ASSERT(flags & O_NONBLOCK); 107 CHECKe(close(listen_fd)); 108 CHECKe(close(accept_fd)); 109 CHECKr(pthread_join(connect_thread, NULL)); 110 return NULL; 111 } 112 113 int 114 main(int argc, char * argv[]) 115 { 116 pthread_t accept_thread; 117 118 CHECKr(pthread_create(&accept_thread, NULL, sock_accept, NULL)); 119 CHECKr(pthread_join(accept_thread, NULL)); 120 SUCCEED; 121 } 122