FreeBSD thread issues

Christophe Yayon lists at nbux.com
Tue Aug 23 09:12:42 CEST 2005


Hi again,

After some discussions on freebsd-hackers mailling list, here is a resume :

1. There a recommendation (or a suggestion) for what to do after a fork() :
http://www.opengroup.org/onlinepubs/009695399/functions/pthread_atfork.html
"In other words "It is suggested that programs that use fork() call an
exec function very soon afterwards in the child process, thus resetting
all states. In the meantime, only a short list of async-signal-safe
library routines are promised to be available."
Note *suggested*. This is a recommendation to protect against a shoddy
pthread-implementation. The thread specifications rule that only the
thread calling fork() is duplicated, which initially leads to the
recommendation (other threads holding locks aren't around to release them
in the new execution context).


2. it appears that Nagios do after a fork :
in base/util.c:
        (1) Become the process group leader by calling setpgid(0, 0);
        (2) something called set_all_macro_environemt_vars(TRUE).
            This calls snprintf a bunch, as well as set variables
            by saving them to malloced memory.  This save is done
            with strcpy and strcat.  setenv is then called to try to
            export them.  memory is then freed with free(3).
        (3) All signal handlers are reset
        (4) The right part of the pipe is closed
        (5) sigalarm handler is created and an alarm set.
        (6) Checks to see if it executing an embedded perl script,
            then tries to execute it if so.  This has the feel of
            being too much after the fork.
        (7) Calls popen on the command if not.
        (8) Reads the output of the command using fgets.
        (9) closes the other end of the pipe
        (10) unsets all env vars.
        (11) Calls _exit()

in base/checks.c
        (1) set_all_macro_environment_vars(TRUE)
        (2) forks again
        (3) granchild:
                resets handler, setpgid, etc.
                if perl script, do embedded perl, otherwise popen.
                lots of read/write to pipe.

likewise in base/commands.c fork is also called for similar things.
There's other places that also call popen...


3. You can only execute async-signal-safe functions after a fork()
from a threaded application.  free(), malloc(), popen(), fgets(),
are not async-signal-safe.  The list of async-signal-safe functions
are here: http://www.opengroup.org/onlinepubs/009695399/nframe.html
The restriction on fork() is here (20th bullet down):
http://www.opengroup.org/onlinepubs/009695399/nframe.html


4. Some FreeBSD developpers think that handling fork() in libpthread (and
probably libthr) than was done in libc_r.  We thought it better not to try
and reinitialize libpthread (and to some extent libc) because
it is messy and to expose non-portable applications.



Possibles solutions :

a. (the best, i think) Trying to modify Nagios code to respect the
recommendation (1.). We are talking about portability and not
performance...

b. a possible workaround for Nagios FreeBSD (and i think other Unix
systems, except Linux) is to use another threads library. For FreeBSD it
seems that uising GNU/pth (which is in the ports) seems to completely
resolve the problem (but i think it's ugly to have to use another -not
native- threads lib...).



What do you think about this ?
Sorry for my english (i am french...)


PS : thanks to all freebsd-hackers posters which permit to resume the
problem (Warner Losh, Daniel Eischen, Alexey Vesnin).




-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf




More information about the Developers mailing list