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

Reply via email to