Page 1 of 1

Re: [Nagios-devel] Re: Re: FreeBSD thread issues

Posted: Tue Aug 23, 2005 1:05 am
by Guest
Christophe Yayon wrote:
> 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/009 ... tfork.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.

In a proper implementation they are. Read malloc/malloc.c from
glibc-2.3.5 and you'll see. The first line of it reads

"/* Malloc implementation for multiple threads without lock contention"

fgets() must also be async-safe, since it's passed its storage-buffer
from the calling function. It can contain races if several threads (or
programs for that matter) tries to read FIFO's at the same time or are
trying to store things to the same piece of memory, but that's neither
new, strange or in any way non-obvious. Obviously, fgets() relies on
lower-level IO code which must be thread-safe (read() in this case) on
account of them being syscalls inside multitasking kernels.

popen() forks and calls execve immediately. If this isn't thread-safe
then there's no way of executing external programs in multithreaded
applications short of implementing popen() directly (which isn't exactly
difficult, but still).

> The list of async-signal-safe functions
> are here: http://www.opengroup.org/onlinepubs/009 ... frame.html
> The restriction on fork() is here (20th bullet down):
> http://www.opengroup.org/onlinepubs/009 ... frame.html
>

Both of those links point to the same document, which is just the
frameset for the navigation-frames.

For async-safe functions, this is the proper url;
http://www.opengroup.org/onlinepubs/009 ... g_02_09_01

For the fork() specification, the doc is here;
http://www.opengroup.org/onlinepubs/009 ... /fork.html

The 20'th bullet is this;
-----------
"A process shall be created with a single thread. If a multi-threaded
process calls fo

...[email truncated]...


This post was automatically imported from historical nagios-devel mailing list archives
Original poster: [email protected]