Ivan Skytte Jørgensen wrote:
> Ivan Skytte Jørgensen wrote:
>> The documentation of pthread_atfork() does say that the handlers can
>> only use async-signal-safe functions because the handlers must at
>> least be able to lock and unlock mutexes.
> I made a slight error there. The documentation does NOT say that
> pthread_atfork handlers are limited to async-signal-safe function.
Yes, it does. Or at least, the CHILD handlers are, because they occur in the
child after forking, and are therefore subject to fork's async-safety rule.
Now, there's no rule that CHILD handlers need to be the converse of PREPARE
handlers, so in theory you might lock mutexes in the PREPARE handler and
just ignore them in the CHILD handler. There would be some value in program
consistency (at least in some cases) to having PREPARE and PARENT handlers
that locked and unlocked mutexes to ensure that the child's state is
consistent. Unfortunately, there's no legal/portable/reliable way for the
child process to unlock. But it CAN depend on having consistent application
state, if you've properly used PREPARE/PARENT handlers and can make the
child code paths avoid the mutexes.
> The rationale for pthread_atfork() explicitly say "The expected usage
> is that the prepare handler acquires all mutex locks and the other two
> fork handlers release them"
Unfortunately, RATIONALE is explicitly not part of the standard. It's just
commentary, history, and miscellaneous ramblings. Nowhere in THE STANDARD
is it suggested that one may/should/could manipulate mutexes in the atfork
handlers. Weird, but true.
> It basically boils down to what pthread_atfork() handlers are intended
> to do they cannot do (portably/reliably).
> My experiments show that pthread_atfork handlers can do
> pthread_mutex_lock/unlock when the fork() is done in a controlled
> manner, but you cannot assume much beyond that.
The earlier paragraph suggests you know this, but just to accentuate it for
everyone... Your expermiments can only show that YOUR particular use
HAPPENS to work in the exact circumstances you've tested, on a PARTICULAR
version of a particular system. Don't read too much into that. When the
standard says that a standard function cannot be used for the intended
purpose, you're starting out from a rather bad position. ;-)
> The thing that initially cought my attention was that it almost worked
> on HP-UX - the only symptom was that any system call that specified a
> timeout would use 100% CPU until the timeout expired.
Nice that was the only symptom. I suppose there are even situations where
one might not consider that a serious problem. But somehow this reminds me
of a line from a book, where the character describes having seen a
competition offroad motorcycle fall from a cliff and suffer no damage other
than a slightly bent fork and a dead rider... ;-)
> Anyway, the issue is solved for my program because I luckily could
> modify the main program to call a reinitialize-after-fork function
> that spawns the background threads again.
Again, while this may work on a particular system under specific
circumstances, the standard says you can only call async-signal safe
functions in the forked child prior to a call to an exec*() function. That
means you cannot "reinitialize" most things, and you certainly cannot
create new threads.
Yes, I like that. "The straw that smashed the camel flat." I'll have to
remember to start using that. It's so much more, uh, "graphic". ;-)
--
/--------------------[ David.Buten...@hp.com ]--------------------\
| Hewlett-Packard Company Tru64 UNIX & VMS Thread Architect |
| My book: http://www.awl.com/cseng/titles/0-201-63392-2/ |
\----[ http://homepage.mac.com/dbutenhof/Threads/Threads.html ]---/