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

Support forum for Nagios Core, Nagios Plugins, NCPA, NRPE, NSCA, NDOUtils and more. Engage with the community of users including those using the open source solutions.
Locked
Guest

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

Post by Guest »

Christophe Yayon wrote:
> Hi all,
>
> here is the answer of FreeBSD-hackers list :
>
>
> This posting demonstrates a fundamental confusion between thread-safe and
> async-safe. That is the root of the problem in the communication.
> Thread-safe functions are a dime a dozen and relatively easy to write.
> async-safe functions are very rare and much harder to do useful things
> with. I've tried to explain the difference below using fgets() as an
> example of the difficulties.
>

Umm... Feels like either me or those guys are missing a third distinction.

* thread-safe; function is guaranteed not to modify global state which
other threads depend on (fgets(), f.e.)

* async-safe (async-IO-safe, really); function is guaranteed not to
block or mess up in IO due to other threads (read(), write() et al.
fgets isn't in here when I come to think of it, because if you fgets()
in two separate threads on the same FILE* pointer you'll end up with
undefined behaviour).

* async-signal-safe; function is guaranteed to only modify parameters it
has been passed and may be re-entered any number of times at any point
of execution.

Given that fork() itself is listed in the table of async-signal-safe
functions I interpret this as thread-safe functions being enough in the
child, provided that it won't read or write to FILE* pointers that were
open prior to the fork() call (or any other such thing that might occur).

If these distinctions are wrong, I need to have this clarified before I
can budge.

>
>>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.
>
>
> fgets need not be async-safe, but it does need to be thread-safe.
> When one fork after pthread_create, one may only call async-safe
> functions. The weaker requirements of thread safety can be shown to
> not necessarily be async safe. If two different threads call fgets(),
> mutexes will keep one thread from running if the other is in the
> middle of changing the FILE * internal state. However, if that thread
> is interrupted by the scheduler with the mutex held, and fork() is
> called, then the new copy of the address space will still have that
> mutex held.


So the child can't use the FILE* pointers opened (and used) in the
parent. Nothing new under the sun (although without threads the only
issue is races). If the child fopen()'s a file of its own there will be
no lock contention and everyone will be happy.

> Any attempt by this new process, with its own address
> space, to acquire the lock is doomed to failure. Since the parent and
> child execute in different address spaces, there is no way for a
> thread that does not exist in the child to unlock the locked mutex.
>
>
> Normally this happens like so:
>
> Thread A Thread B
>
> fgets(fp, b1, 10);
> lock fp's mutex
> copy 5 available bytes into b1
>
> fgets(fp, b2, 10)
> try lock fp's mutex
>
> unlock fp's mutex
> return
>
> attempt to lock finishes
> b2 can be updated
> unlock mutex.
>
> However, in the fork case:
>
> Thread A Thread B
>
> fgets(fp, b1, 10);
> lock fp's mutex
> copy 5 available bytes into b1
>
>

...[email truncated]...


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