From owner-freebsd-current Thu Sep 10 10:55:19 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id KAA16387 for freebsd-current-outgoing; Thu, 10 Sep 1998 10:55:19 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from plunger.gdeb.com (plunger.gdeb.com [153.11.11.3]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id KAA15827 for ; Thu, 10 Sep 1998 10:53:41 -0700 (PDT) (envelope-from eischen@vigrid.com) Received: from clcrtr.clc.gdeb.com ([153.11.109.11]) by plunger.gdeb.com with ESMTP (1.37.109.16/CSC-E_1.8) id AA179496620; Thu, 10 Sep 1998 12:57:00 -0400 Received: from clcrtr.clc.gdeb.com (clcrtr [153.11.109.129]) by clcrtr.clc.gdeb.com (8.8.8/8.7.3) with SMTP id MAA09198; Thu, 10 Sep 1998 12:54:13 -0400 (EDT) Message-Id: <35F80435.41C67EA6@vigrid.com> Date: Thu, 10 Sep 1998 12:54:13 -0400 From: "Daniel M. Eischen" X-Mailer: Mozilla 3.0Gold (X11; I; FreeBSD 2.2.6-STABLE i386) Mime-Version: 1.0 To: info@highwind.com Cc: freebsd-current@FreeBSD.ORG, tlambert@primenet.com, eischen@vigrid.com Subject: Re: Thread Problems Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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() > It looks like the problem lies in the threads implementation of fork and execve. When you fork, the child process gets a copy of the parents file descriptors, which includes the listen socket. When you exec, the threads library goes through its list of file descriptors and returns their mode to non-blocking (unless the application explicitly sets the mode to non-blocking). You can see this in uthread_execve.c: /* * Enter a loop to set all file descriptors to blocking * if they were not created as non-blocking: */ for (i = 0; i < _thread_dtablesize; i++) { /* Check if this file descriptor is in use: */ if (_thread_fd_table[i] != NULL && !(_thread_fd_table[i]->flags & O_NONBLOCK)) { /* Get the current flags: */ flags = _thread_sys_fcntl(i, F_GETFL, NULL); /* Clear the nonblocking file descriptor flag: */ _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK); } } I'm not exactly sure how the threads library should be fixed to Do The Right Thing, though. How can the threads library know what files are going to be used? Perhaps it can flag the file as a socket when it is created and not clear the non-blocking flag in this case... A simple solution that you can make in your application, is to close all relevent sockets after the fork and before the execl. When you close the file, it will not affect the non-blocking flag. Your code will have to make the sockets visible to the forkExec routine so it can close them. Another method is to perform the forkExec before you create the sockets, although this may not be possible in your real application. Dan Eischen eischen@vigrid.com *************** *** 16,26 **** #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 --- 16,27 ---- #include unsigned short port = 20000; + int fd; void *acceptThread(void *) { // Create the socket ! fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { ::printf("socket failed"); } // Make it reusable *************** *** 117,122 **** --- 118,126 ---- } if (!pid) { // In Child + // Close the socket + ::close (fd); + // Enter our own process group (avoids signal nastyness) if (::setsid() == -1) { ::_exit(EXIT_FAILURE); To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message