Почему POSIX требует, чтобы система (3) игнорировала SIGINT и SIGQUIT? - PullRequest
1 голос
/ 09 мая 2019

Спецификация POSIX гласит:

Функция system () должна игнорировать сигналы SIGINT и SIGQUIT и должна блокировать сигнал SIGCHLD, ожидая завершения команды.Если это может привести к тому, что приложение пропустит сигнал, который убил бы его, то приложение должно проверить возвращаемое значение из system () и предпринять любое действие, соответствующее приложению, если команда прервалась из-за получения сигнала.

Это означает, что у программы, которая запускает длительный подпроцесс, будут SIGINT и SIGQUIT заблокированы на долгое время.Вот тестовая программа, скомпилированная на моем ноутбуке Ubuntu 18.10:

$ cat > test_system.c <<< EOF
#include <stdlib.h>

int main() {
    system("sleep 86400");  // Sleep for 24 hours
}
EOF
$ gcc test_system.c -o test_system

Если я запускаю эту тестовую программу, работающую в фоновом режиме ...

$ ./test_system &
[1] 7489

.. Тогда я вижу, чтоSIGINT (2) и SIGQUIT (3) помечены как игнорируемые в битовой маске.

$ ps -H -o pid,pgrp,cmd,ignored
  PID  PGRP CMD                                  IGNORED
 6956  6956 -bash                       0000000000380004
 7489  7489   ./test_system             0000000000000006
 7491  7489     sh -c sleep 86400       0000000000000000
 7492  7489       sleep 86400           0000000000000000

Попытка уничтожить test_system с помощью SIGINT не имеет никакого эффекта ..

$ kill -SIGINT 7489

.. Но отправка SIGINT в группу процессов действительно уничтожает его (это ожидается, это означает, что каждый процесс в группе процессов получает сигнал - режим сна завершится и система вернется).

   $ kill -SIGINT -7489
   [1]+  Done                    ./test_system

Вопросы

  1. Какова цель игнорирования SIGINT и SIGQUIT, поскольку процесс все еще можно завершить с помощью группы процессов (это происходит, когда вы делаете ^C втерминал).
  2. Бонусный вопрос: почему POSIX требует, чтобы SIGCHLD был заблокирован?
  3. Обновление Если SIGINT и SIGQUIT игнорируются, чтобы гарантировать, что мыне оставляйте детей, тогда почему нет обработки для SIGTERM - это сигнал по умолчаниют убить!

1 Ответ

1 голос
/ 09 мая 2019

SIGINT и SIGQUIT - сигналы, генерируемые терминалом. По умолчанию они отправляются в группу процессов переднего плана, когда вы нажимаете Ctrl+C или Ctrl+\ соответственно.

Я считаю, что идея игнорировать их при запуске ребенка через system заключается в том, что терминал должен быть таким, как если бы он был временно принадлежит ребенку, а Ctrl+C или Ctrl+\ должны временно влиять только на ребенка и его потомков. , а не родитель.

SIGCHLD заблокирован, так что system, вызванный дочерним завершением SIGCHLD, не вызовет обработчик SIGCHLD, если он у вас есть, потому что такой обработчик SIGCHLD может пожинать запущенный дочерний элемент на system до того, как system пожнет его.

...