summaryrefslogtreecommitdiff
path: root/regress/lib/libpthread/socket/3/socket3.c
diff options
context:
space:
mode:
Diffstat (limited to 'regress/lib/libpthread/socket/3/socket3.c')
-rw-r--r--regress/lib/libpthread/socket/3/socket3.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/regress/lib/libpthread/socket/3/socket3.c b/regress/lib/libpthread/socket/3/socket3.c
new file mode 100644
index 00000000000..03242f6768f
--- /dev/null
+++ b/regress/lib/libpthread/socket/3/socket3.c
@@ -0,0 +1,121 @@
+/* $OpenBSD: socket3.c,v 1.1 2002/10/10 00:45:20 marc Exp $ */
+/* PUBLIC DOMAIN Oct 2002 <marc@snafu.org> */
+
+/* Test blocking/non-blocking mode inheritance on accept */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "test.h"
+
+/*
+ * connect to the test port passed in arg, then close the connection
+ * and return.
+ */
+void *
+sock_connect(void *arg)
+{
+ struct sockaddr_in sin;
+ int port;
+ int sock;
+
+ SET_NAME("connect");
+ port = (int)arg;
+ CHECKe(sock = socket(AF_INET, SOCK_STREAM, 0));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ CHECKe(connect(sock, (struct sockaddr *)&sin, sizeof sin));
+ CHECKe(close(sock));
+ return NULL;
+}
+
+/*
+ * listen for a connection, accept it using a non-blocking socket, and
+ * verify that the blocking mode of the socket returned from accept is
+ * also non-blocking
+ */
+void *
+sock_accept(void *arg)
+{
+ pthread_t connect_thread;
+ struct pollfd fds;
+ struct sockaddr_in sa;
+ struct sockaddr accept_sa;
+ int accept_fd;
+ int accept_sa_size;
+ int flags;
+ int listen_fd;
+ int port;
+
+ SET_NAME("accept");
+
+ /* listen for a connection */
+
+ port = 6543;
+ memset(&sa, 0, sizeof sa);
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ sa.sin_port = htons(port);
+ CHECKe(listen_fd = socket(AF_INET, SOCK_STREAM, 0));
+ printf("listen_fd = %d\n", listen_fd);
+ while (1) {
+ if (bind(listen_fd, (struct sockaddr *)&sa, sizeof(sa)) == 0)
+ break;
+ if (errno == EADDRINUSE) {
+ sa.sin_port = htons(++port);
+ continue;
+ }
+ DIE(errno, "bind");
+ }
+ CHECKe(listen(listen_fd, 2));
+
+ /* Create another thread to connect to the listening socket. */
+ CHECKr(pthread_create(&connect_thread, NULL, sock_connect,
+ (void*)port));
+
+ /*
+ * Use poll to check for a pending connection as the socket
+ * passed to accept will be in non-blocking mode.
+ */
+ fds.fd = listen_fd;
+ fds.events = POLLIN;
+ CHECKe(poll(&fds, 1, INFTIM));
+
+ /*
+ * set non blocking mode on the listening socket and close stdin
+ * (fd 0) so the accept will use fd 0 (needed to test boundary
+ * condition in the pthread accept code).
+ */
+ flags = fcntl(listen_fd, F_GETFL);
+ CHECKr(fcntl(listen_fd, F_SETFL, flags |= O_NONBLOCK));
+ CHECKe(close(STDIN_FILENO));
+ accept_sa_size = sizeof accept_sa;
+ CHECKe(accept_fd = accept(listen_fd, &accept_sa, &accept_sa_size));
+ flags = fcntl(accept_fd, F_GETFL);
+ printf("accept_fd = %d, flags = %x\n", accept_fd, flags);
+ /* XXX the above should abort if flags & O_NOBLOCK is zero */
+ /* ASSERT(flags & O_NONBLOCK); */
+ CHECKe(close(listen_fd));
+ CHECKe(close(accept_fd));
+ CHECKr(pthread_join(connect_thread, NULL));
+ return NULL;
+}
+
+int
+main(int argc, char * argv[])
+{
+ pthread_t accept_thread;
+
+ CHECKr(pthread_create(&accept_thread, NULL, sock_accept, NULL));
+ CHECKr(pthread_join(accept_thread, NULL));
+ SUCCEED;
+}