Wow... I think you're correct, FreeBSD only partially implements POSIX threads. And the bug has been there a long time... I guess their out is the other note that says you really shouldn't mix. But pthread_create() and fork() are very different - pthread_create() shares memory, fork() does not. Sometimes you need one, sometimes the other. ntop with only pthread_create would mean that every access for reporting and update would have to be protected with mutexes and this would kill performance...
copy vs. copy-on-write When you fork(), the UNIX standard is to give the child a completely separate copy of memory. So FreeBSD pretty much has to do this. But, there are two choices. copy - which makes for a long fork() time as an entire copy of memory is made and copy-on-write. With c-o-w, all that's copied is the internal page tables and the physical splitting of a page occurs only when either the parent or child writes to it. This makes fork() much less expensive. I know that Linux does copy-on-write, don't know about the others. It sort of sounds like FreeBSD does copy. Anyway, I'll put a test in the configure file to see if there really is a pthread_atfork() routine and skip the code if it doesn't exist. It's wrong, but no more wrong than ntop has been up until now, so I guess we can live with it. Thanks for looking this up for me. Good find on the bug report... it looks like they just punted: State-Changed-From-To: open->closed State-Changed-By: jasone State-Changed-When: Tue May 23 10:03:29 PDT 2000 State-Changed-Why: There is no plan to add pthread_atfork(), due to the difficulty and limited usefulness of doing so. -----Burton -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Behalf Of Stanley Hopcroft Sent: Sunday, July 13, 2003 10:58 PM To: [EMAIL PROTECTED] Subject: Re: [Ntop] 2.2c won't compile on FreeBSD RELENG_4 (don't know about 5): no pthread_atfork(). Dear Sir, I am writing to thank you for your letter and say, 'trouble trouble trouble, nothing but trouble'. FreeBSD bug bin/17437 (see http://www.FreeBSD.org/cgi/query-pr.cgi?pr=17437) acknowledges this bug as high priority and serious in 2000 ! from the PR ' (Following up on myself, after further investigations): Nope, the above patch is insufficient, it just serves to uncover more bugs... The problem is that libc_r does not do complete cleanup of the other threads after the fork. All deleted threads must be quietly removed from any queues they happen to be waiting in, or they may later be subject to "revival" after they have been freed. Scenario (typical use of pthread_atfork()): - forking thread aquires a number of mutexes. - another thread waits on one of the mutexes - after forking, the mutexes are released, which will make any waiting threads runnable -- but they have been deallocated! - Bad Things(tm) happen... All mutexes where this may happen can be conveniently located via the "mutexq" field of the running thread, so this particular scenario is easily fixed. There is no similar way to handle threads queued on, for example, condition variables, as there is no way to find the head of the "qe" and "pqe" queue entries. The "join_queue" should be emptied too. Basically, right now libc_r does not work at all after a fork(). Regards, /Mikko ' More comment below On Sun, Jul 13, 2003 at 07:49:55PM -0700, Burton Strauss wrote: > Interesting S... if it doesn't implement pthread_atfork(), then there's actually no safe way to run on FreeBSD... I'll dump the text from the man page at the bottom - it makes for interesting reading! > > It's easy enough to #ifdef that stuff out - it's all self contained. I can fix it in the cvs easily too. You won't be any worse off than you were previously... > > But - can you check a couple of things for me re FreeBSD? > > 1. If you fork() does it copy memory or is it shared? > I think the former (copy memory _not_ shared) since 1 2 sample fork program has common values of the common variables and changing the value of a var in the parent does not change that in the child. pc09011> cat z.c #include <stdlib.h> int main(int argc, char *argv[]) { int p1, p_x, p_y ; p_x = 1 ; p_y = 2 ; printf("before fork().\n") ; printf("process [%d] x: %d\n", (int) getpid(), p_x) ; printf("process [%d] y: %d\n", (int) getpid(), p_y) ; if ( (p1 = fork()) == -1 ) { printf("fork() failed.\n") ; exit(1) ; } printf("after fork().\n") ; if ( p1 ) { p_y = 4 ; printf("setting y in parent [%d] .. y: %d\n", (int) getpid(), p_y) ; } else { printf("process [%d] x: %d\n", (int) getpid(), p_x) ; printf("process [%d] y: %d\n", (int) getpid(), p_y) ; } } pc09011> ./z before fork(). process [15371] x: 1 process [15371] y: 2 after fork(). after fork(). setting y in parent [15371] .. y: 4 process [15372] x: 1 pc09011> process [15372] y: 2 pc09011> > 2. What level of POSIX threads does FreeBSD support? (pthreads_atfork() is part of POSIX Threads Extension (1003.1c-1995) - it's even available in Solaris for ghu's sake...) > >From man prthread STANDARDS The functions in libc_r with the pthread_ prefix and not _np suffix or pthread_rwlock prefix conform to ISO/IEC 9945-1:1996 (``POSIX.1''). So this looks like a bug. > > -----Burton > > > > DESCRIPTION > pthread_atfork registers handler functions to be called just before and > just after a new process is created with fork(2). The prepare handler > will be called from the parent process, just before the new process is > created. The parent handler will be called from the parent process, > just before fork(2) returns. The child handler will be called from the > child process, just before fork(2) returns. > > One or several of the three handlers prepare, parent and child can be > given as NULL, meaning that no handler needs to be called at the corre- > sponding point. > > pthread_atfork can be called several times to install several sets of > handlers. At fork(2) time, the prepare handlers are called in LIFO > order (last added with pthread_atfork, first called before fork), while > the parent and child handlers are called in FIFO order (first added, > first called). > > To understand the purpose of pthread_atfork, recall that fork(2) dupli- > cates the whole memory space, including mutexes in their current lock- > ing state, but only the calling thread: other threads are not running > in the child process. The mutexes are not usable after the fork and > must be initialized with pthread_mutex_init in the child process. This > is a limitation of the current implementation and might or might not be > present in future versions. > > > Yours sincerely. -- ------------------------------------------------------------------------ Stanley Hopcroft ------------------------------------------------------------------------ _______________________________________________ Ntop mailing list [EMAIL PROTECTED] http://listgateway.unipi.it/mailman/listinfo/ntop
