Boost logo

Boost :

From: Angus Leeming (angus.leeming_at_[hidden])
Date: 2004-06-23 03:46:55


Jonathan Biggar wrote:

> Angus Leeming wrote:
>> namespace {
>>
>> std::map<pid_t, int> completed_children;
>>
>> int status;
>> sig_atomic_t pid;
>>
>> }
>>
>> extern "C"
>> void child_handler(int)
>> {
>> pid = wait(&status);
>> std::map<pid_t, int>::iterator it =
>> completed_children.find(pid); if (it !=
>> completed_children.end())
>> it->second = status;
>> }
>>
>> I'm pretty sure that the above is safe code. It does the absolute
>> minimum in the handler routine. wait() is guaranteed to be async-safe.
>> Moreover, the handler receives only SIGCHLD signals and so cannot
>> receive multiple calls simultaneaously. However, I'm unsure whether it
>> Ok to search the map like this. Any advice?
>
> That's not safe code, since the child_handler() function could be called
> at any time, interrupting other code that is modifying the
> completed_children map.

Yes, I've thought of that. We just need to block any signals when we're
modifying the map:

unix_reaper::unix_reaper()
{
        signal(SIGCHLD, boost_child_handler);

        sigemptyset(&old_mask_);
        sigemptyset(&new_mask_);
        sigaddset(&new_mask_, SIGCHLD);
}

void unix_reaper::register(pid_t pid)
{
        // Block the SIGCHLD signal.
        sigprocmask(SIG_BLOCK, &new_mask_, &old_mask_);

        // This is the map.
        children_[pid] = -1;

        // Unblock the SIGCHLD signal and restore the old mask.
        sigprocmask(SIG_SETMASK, &old_mask_, 0);
}

Does this address your concern?
Angus


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk