From owner-freebsd-current Thu Sep 10 06:46:51 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id GAA26180 for freebsd-current-outgoing; Thu, 10 Sep 1998 06:46:51 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from highwind.com (hurricane.highwind.com [209.61.45.50]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id GAA26160 for ; Thu, 10 Sep 1998 06:46:46 -0700 (PDT) (envelope-from info@highwind.com) Received: (from info@localhost) by highwind.com (8.8.6/8.8.6) id JAA16724; Thu, 10 Sep 1998 09:46:24 -0400 (EDT) Date: Thu, 10 Sep 1998 09:46:24 -0400 (EDT) Message-Id: <199809101346.JAA16724@highwind.com> From: HighWind Software Information To: tlambert@primenet.com CC: eischen@vigrid.com, eischen@vigrid.com, tlambert@primenet.com, freebsd-current@FreeBSD.ORG In-reply-to: <199809100537.WAA07306@usr06.primenet.com> (message from Terry Lambert on Thu, 10 Sep 1998 05:37:27 +0000 (GMT)) Subject: Re: Thread Problems Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG Okay, I coded up a test program that ALWAYS reproduces this accept() blocking problem we have been talking about. Check it out: % uname -a FreeBSD zonda.highwind.com 3.0-19980831-SNAP FreeBSD 3.0-19980831-SNAP #0: Mon Aug 31 14:03:19 GMT 1998 root@make.ican.net:/usr/src/sys/compile/GENERIC i386 My libc_r is EXTREMELY up-to-date. ~2 days old. The program does the following: 1. spawns an a thread to loop on "accept" 2. fork/exec's a child talking down a socket pair 3. loops in main() To compile: g++ -o fbsd -D_REENTRANT -D_THREAD_SAFE -Wall -Werror -g fbsdtest.C -pthread To run: ./fbsd 10000 It'll bind to port 10000, and start printing messages on stdout, then from another window: "telnet localhost 10000". You'll see the main() thread STOP printing. ONLY the accept() thread will continue to work. Help would be greatly appreciated... -Rob ---- /***************************************************************************** File: fbsdtest.C Contents: FreeBSD accept and fork test Created: 10-Sep-1998 *****************************************************************************/ #include #include #include #include #include #include #include unsigned short port = 20000; void *acceptThread(void *) { // Create the socket int fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { ::printf("socket failed"); } // Make it reusable int optval = 1; if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&optval), sizeof(optval)) == -1) { ::printf("Reusable failed"); } // Bind it sockaddr_in location; ::memset(&location, 0, sizeof(location)); location.sin_family = AF_INET; location.sin_addr.s_addr = htonl(INADDR_ANY); location.sin_port = htons(port); if (::bind(fd, reinterpret_cast(&location), sizeof(location)) == -1) { ::printf("Bind failed"); } // Listen on it if (::listen(fd, 128) == -1) { ::printf("Listen failed"); } // LOOP forever accepting and closing! while (true) { sockaddr_in info; int length = sizeof(info); int fd2 = ::accept(fd, reinterpret_cast(&info), &length); ::printf("Got an accept()\n"); ::close(fd2); } } pthread_t spawnBoundThread(void *(*function)(void *)) { pthread_t tid; pthread_attr_t attr; // Initialize thread attributes if (::pthread_attr_init(&attr)) { ::printf("Init Failed"); return 0; } // Set detached if (::pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) { ::printf("Detach failed"); return 0; } // Set stack size if (::pthread_attr_setstacksize(&attr, 131072)) { ::printf("Stack set failed"); return 0; } // Spawn the thread if (::pthread_create(&tid, &attr, function, 0)) { ::printf("Thread start failed"); return 0; } // Cleanup thread attributes if (::pthread_attr_destroy(&attr)) { ::printf("Cleanup failed"); return 0; } // Return the thread id return tid; } int forkExec(const char *program, const char *arg1) { // Create the socketpair; int fds[2]; if (::socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { return -1; } // FORK!! *Youch!* pid_t pid = ::fork(); if (pid == -1) { if (::close(fds[0]) || ::close(fds[1])) { return -1; } return -1; } if (!pid) { // In Child // Enter our own process group (avoids signal nastyness) if (::setsid() == -1) { ::_exit(EXIT_FAILURE); } // Dup the descriptor to STDIN and STDOUT if (::dup2(fds[1], STDOUT_FILENO) == -1 || ::dup2(fds[1], STDIN_FILENO) == -1) { ::_exit(EXIT_FAILURE); } // Close the other side of the socketpair. if (::close(fds[0])) { ::_exit(EXIT_FAILURE); } // Run the appropriate program ::execl(program, program, arg1, 0); ::_exit(EXIT_FAILURE); } // In Parent if (::close(fds[1])) { return -1; } return fds[0]; } int main(int, char **argv) { port = atoi(argv[1]); // Setup 1 second timeout timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; spawnBoundThread(acceptThread); // Sleep for a second ::select(0, 0, 0, 0, &timeout); int childFD = forkExec("/bin/sleep", "200"); if (childFD == -1) { return EXIT_FAILURE; } while (true) { // Sleep for a second ::select(0, 0, 0, 0, &timeout); ::printf("main() is still alive\n"); } ::close(childFD); return EXIT_SUCCESS; } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message