Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Aug 2001 21:56:10 -0700 (PDT)
From:      Joel Ray Holveck <joelh@juniper.net>
To:        hackers@freebsd.org
Subject:   Thoughts on this pthreads bug: why release O_NONBLOCK in _exit?
Message-ID:  <200108300456.f7U4uAR08305@sindri.juniper.net>

next in thread | raw e-mail | index | archive | help
I've been studying a few things in pthreads to figure out a bug that's
had me banging my head against a wall.  I'd be interested in knowing
what peoples' thoughts are.

The basic scenario is that a fd loses its schedulability after the
process calls daemon().  To review:

The current pthreads implementation requires fds to be marked
O_NONBLOCK (which pthreads manages itself) to allow scheduling to work
properly.

The daemon() library call's life (for the purposes of this discussion)
is to fork.  The parent dies by calling _exit(0), and the child goes
on.

The _exit routine in libc_r turns off the O_NONBLOCK flag on all file
descriptors, except those which the program turned it on for.

Now, the problem.

The forked parent and child, of course, are sharing fds.  So when the
forked child exits, the parent's fds have their O_NONBLOCK flags
toggled off.  If the parent is still running multithreaded, this
creates a scheduling problem.

I've included a condensed version of the code I've been using to test
this below.  It's enough to demonstrate the problem, if not the normal
symptoms.

What I can't figure out is why libc_r's _exit toggles off the
O_NONBLOCKs.

Any thoughts?

Thanks,
joelh

#include <stdio.h>
#include <err.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

int
main(int argc, char *argv)
{
    pid_t pid;
    int fd;
    
    fd = socket(PF_UNIX, SOCK_DGRAM, 0);
    printf("flags after open: %x\n", _thread_sys_fcntl(fd, F_GETFL));
    fflush(stdout);
    pid = fork();
    if (pid != 0) {
	printf("flags after fork in parent: %x\n",
	       _thread_sys_fcntl(fd, F_GETFL));
	fflush(stdout);
	/* We use _exit instead of exit to imitate what daemon()
	 * does. */
	_exit(0);
    } else {
	sleep(1); /* Give the parent time to die */
	printf("flags after fork in child: %x\n",
	       _thread_sys_fcntl(fd, F_GETFL));
	exit(0);
    }
}

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200108300456.f7U4uAR08305>