Как я могу получить PID установленного процесса в обработчике своего собственного SIGCHLD? - PullRequest
0 голосов
/ 10 апреля 2019

Я пишу игрушечную оболочку для университета, и мне нужно обновить статус фонового процесса, когда он закончится.Поэтому мне пришла в голову идея заставить обработчик SIGCHLD сделать это, поскольку этот сигнал отправляется по окончании процесса.Проблема в том, что для реализации команды jobs мне нужно обновить статус с «запущен» на «завершен», и сначала мне нужно найти этот конкретный процесс в массиве, который я ему выделил, и один из способов:сделать это путем поиска по pid, так как массив хранит информацию, отображаемую в jobs.Каждая запись хранит pid процесса, статус (который является строкой) и саму команду.

Теперь вопрос: есть ли способ получить pid процесса, который вызвал сигнал, когда он закончился?

В данный момент моя функция-обработчик выглядит следующим образом:

void handler(int sig){
    int child_pid;
    child_pid = wait(NULL);
    //finds the process with a pid identical 
    //to child_pid in the list and updates its status
    ...
}

Поскольку wait(NULL) возвращает pid первого процесса, который заканчивается с момента его вызова, статус обновляется только тогда, когда другойфоновый процесс завершается, и поэтому обновляется неправильный статус процесса.

Мы не слишком много разбирались в функциях wait() и waitpid(), за исключением того, что они ожидают завершения процесса, поэтому любая информацияможет быть полезным.

1 Ответ

0 голосов
/ 11 апреля 2019

Хотя использование обработчика сигнала в обработчике сигналов не очень хорошая идея, вы можете выполнить следующее, чтобы выполнить то, что вы пытаетесь сделать.

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, потомок пожинается в методе-обработчике, а затем «ожидание процесса переднего плана» никогда не завершается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...