Что определяет, получат ли фоновые процессы сценария сигнал SIGINT от терминала?

когда вы устанавливаете chrome, skype или any.deb и сталкиваетесь с этой проблемой, просто запустите «apt install -f»

sudo apt install -f

Это решит проблему или удалит поврежденный пакет, если нет шансов.

3
21.06.2020, 22:20
1 ответ

Перехват сигнала? распространение? Нет

waitне перехватывает сигнал. Оболочка его не пропускает. Сигнал не перехватывается и не передается. Подоболочки, выполняющие ваши три «фоновые» команды, либо получают сигнал напрямую , либо нет.

Вы можете протестировать следующий скрипт:

#!/usr/bin/env bash

printf 'My PID is %s.\n' "$$"
sleep 15 && echo '123' &
sleep 15 && echo '456' &
sleep 15 && echo '999' &
wait < <(jobs -p)

Сценарий ведет себя так же, как ваш сценарий с wait. Я имею в виду, что вы можете завершить и три «фоновых» задания с помощью Ctrl + C .

Запустите еще раз и не нажимайте Ctrl + C . Скрипт сообщит вам свой собственный PID ($$). Теперь, если вы отправите SIGINTс другого терминала (kill -s INT <pid_here>), он завершит сценарий, но , а не три задания.

Но если отправить SIGINTвсей группе процессов (kill -s INT -- -<pid_here>), то скрипт и задания получат его. То же самое происходит, когда вы нажимаете Ctrl + C и ваш терминал настроен на отправку сигнала прерывания при нажатии клавиши (, как это обычно бывает, stty -aвключает intr = ^C), Вся группа получает сигнал.


Кто получает сигнал?

Речь идет о группе процессов переднего плана. Одной из задач, которую выполняет оболочка, является информирование терминала о том, какая группа процессов находится на переднем плане.

A terminal may have a foreground process group associated with it. This foreground process group plays a special role in handling signal-generating input characters […].

A command interpreter process supporting job control can allocate the terminal to different jobs, or process groups, by placing related processes in a single process group and associating this process group with the terminal. […]

(источник)

Вот что действительно происходит в вашем случае:

  1. Сначала вы находитесь в интерактивной оболочке. Оболочка является лидером своей собственной группы процессов (с идентификатором группы процессов, равным PID оболочки ).Терминал распознает эту группу процессов как группу процессов переднего плана.
  2. В указанной оболочке включено управление заданиями. (Обычно оболочки, поддерживающие управление заданиями, включают его по умолчанию при работе в интерактивном режиме. )Когда вы запускаете сценарий (или любой другой не -встроенный ), оболочка делает его лидером другой группы процессов. Терминалу сообщается, что новая группа процессов теперь должна рассматриваться как группа процессов переднего плана. Таким образом, интерактивная оболочка отодвигается на задний план.
  3. Из шебанга мы знаем, что это bashинтерпретация сценария. Неинтерактивный -Bash запускается с отключенным по умолчанию управлением заданиями. Команды, выполняемые ею, не станут лидерами своих собственных групп процессов (, если только сама команда не изменит свою группу процессов; возможно, но в вашем случае этого не происходит ). Три подоболочки и три процесса sleepпринадлежат к той же группе процессов, что и запущенный скрипт.
  4. Когда сценарий завершается, терминал информируется о том, что группа процессов интерактивной оболочки теперь должна считаться группой процессов переднего плана (снова ). Если какой-либо процесс из группы процессов сценария все еще выполняется, он больше не будет находиться в группе процессов переднего плана.

Это объясняет поведение, которое вы наблюдали:

  • Если скрипт запущен, когда вы нажимаете Ctrl + C , тогда он и практически все его потомки получат SIGINT. Неважно, ждет ли скрипт из-за waitили из-за какой-то команды, выполненной без &. Важно то, что его группа процессов по-прежнему является группой процессов переднего плана, и (великие )дети принадлежат к группе.

  • Если скрипт больше не запускается, когда вы нажимаете Ctrl + C , то его потомки (, если таковые имеются, )не получат SIGINT, потому что они не принадлежат в текущую группу процессов переднего плана.


Игра с управлением заданиями

Обратите внимание, что вы можете изменить это поведение, отключив или включив управление заданиями.

Если вы отключите управление заданиями(set +m)в интерактивной оболочке и запустите сценарий, оболочка запустит сценарий, не сделав его лидером группы процессов. В скрипте нет управления заданиями. Сценарий и в основном все его дочерние элементы будут принадлежать группе процессов интерактивной оболочки. Эта группа будет группой процессов переднего плана все время. После Ctrl + C все процессы (, включая интерактивную оболочку ), получат SIGINT, независимо от того, запущен скрипт или нет.

Если вы включите управление заданиями(set -m)в самом скрипте, три подоболочки будут помещены в соответствующие группы процессов. В подобных обстоятельствах команда без &стала бы лидером группы процессов, и терминал был бы проинформирован о новой группе процессов переднего плана. Но ваши команды с &, они станут лидерами, но группа процессов переднего плана не изменится. После Ctrl + C они не получат SIGINT, независимо от того, запущен скрипт или нет, и независимо от того, включено ли в интерактивной оболочке управление заданиями.


Примечания

  • Разделитель или терминатор &не означает «запускать в фоновом режиме». Это означает только «запускать асинхронно». Команды, выполняемые с &, могут оставаться в группе процессов переднего плана (, например. если управление заданиями отключено ). Команды, запущенные без &, могут покинуть группу процессов переднего плана.

  • Вас может удивить тот факт, что интерактивная оболочка помещает себя в фоновый режим при выполнении команд. Это действительно происходит. Запустите эти команды в интерактивном Bash:

    set -m
    trap 'echo "Signal received."' INT
    sleep 999
    

    Ctrl + C

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

    Теперь измените set -mна set +mи запустите снова:

    set +m
    trap 'echo "Signal received."' INT
    sleep 999
    

    Ctrl + C

    При отключенном управлении заданиями sleepбудет выполняться в группе процессов оболочки. Группа все время будет группой процессов переднего плана. Вы увидите сообщение от trap.

3
18.03.2021, 23:25

Теги

Похожие вопросы