Хотя использование обработчика сигнала в обработчике сигналов не очень хорошая идея, вы можете выполнить следующее, чтобы выполнить то, что вы пытаетесь сделать.
void handler(int sig){
int child_pid;
int status;
child_pid = waitpid(-1, &status, WUNTRACED | WNOHANG);
if(child_pid > 0)
{
// your code
// make sure to deal with the cases of child_pid < 0 and child_pid == 0
}
}
То, что вы делаете, не является технически неправильным, однако было бы лучше использовать waitpid
. Когда вы используете waitpid(-1,...)
, это работает аналогично тому, как вы использовали wait(...)
, и будет ожидать не только указанный процесс, но и любой процесс, который завершится. Основное отличие состоит в том, что вы можете указать WUNTRACED
, который будет приостанавливать выполнение до тех пор, пока процесс в наборе ожидания не будет завершен или остановлен. WNOHANG
скажет waitpid
не приостанавливать выполнение процесса. Вы не хотите, чтобы ваш обработчик был приостановлен.
Если несколько сигналов отправляются в один и тот же процесс, т. Е. Из-за одновременного завершения нескольких дочерних процессов, то будет казаться, что был отправлен только один сигнал, потому что обработчик сигналов не будет выполнен снова. Это связано с тем, как сигналы отправляются; когда сигнал создается, он помещается в таблицу исключений, чтобы процесс затем «получил» его; сигналы не используют очереди. Чтобы учесть это, вам нужно будет перебирать вызов waitpid(-1,...)
, пока он не вернет 0, чтобы убедиться, что вы пожинаете всех прерванных потомков.
Кроме того, следите за тем, где еще вы пожинаете ребенка (обратите внимание, что если ребенок уже был пожинен, то waitpid
вернет 0, если вы используете флаг WNOHANG
). Я бы предположил, что именно это приводит к тому, что поведение, которое вы видите, обновляется только после завершения другого фонового процесса. Например, поскольку вы создаете игрушечную оболочку, я предполагаю, что вы где-то ожидаете процессов переднего плана, и если вы используете функцию ожидания там, а также в своем обработчике, вы можете получить одну из двух вещей. Дочерний объект пожинается в методе «ожидания процесса переднего плана», а затем, когда выполняется обработчик, ему нечего пожинать. И 2, потомок пожинается в методе-обработчике, а затем «ожидание процесса переднего плана» никогда не завершается.