ловушка программы в bash - PullRequest
0 голосов
/ 10 января 2019

, что я пытаюсь, это мой пример c kill (), который убивает один процесс. Но я хочу поймать это уничтожение через скрипт bash, чтобы моё выполнение было выполнено правильно.

У меня есть небольшой пример, который убивает процесс.

#include <signal.h>

int main(void)
{
  printf("before kill");
  kill(0, SIGTERM); // 2265 is a process pid id
  printf("after kill");
}

Теперь я хочу поймать это убийство в скрипте bash. После генерации двоичного файла с помощью команды gcc выполните скрипт, и ничего не происходит.

Мой bash выглядит так:

#!/usr/bin/env bash
term() {
./helloapp
 echo "bash caught TERM"

 }
trap term SIGTERM

Но он ничего не делает. Любое предложение или помощь высоко ценится.

1 Ответ

0 голосов
/ 10 января 2019

Обработка сигналов оболочки

У меня есть небольшой пример, который убивает процесс.

#include <signal.h>

int main(void)
{

  kill(0, SIGTERM);
}

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

Мой bash выглядит так:

#!/usr/bin/env bash
term() {
./helloapp
 echo "bash caught TERM"

 }
trap term SIGTERM

Но он ничего не делает.

Предположим, что ./helloapp - это процесс, который будет посылать сигнал, вы совершенно не поняли, как bash использует обработку сигналов. Я подозреваю, что это может отражать неправильное понимание обработки сигналов в целом.

Вы написали функцию обработчика сигнала так, как будто она предоставляет какую-то область обработки сигнала для команд внутри, например, блока try в Java. Но сигналы не аналогичны исключениям Java. Они асинхронные, вне нормального потока управления. Исключения могут приводить к передаче управления, которая в противном случае была бы невозможна, но они все еще действуют в рамках общего потока программы. Не так обработка сигналов.

Команда Bash trap не выполняет именованную функцию оболочки. Скорее, он регистрирует как обработчик для указанных сигналов. Если этот процесс оболочки впоследствии получит один из назначенных сигналов, то функция будет работать вместо поведения по умолчанию для этого сигнала. В этом случае это может помешать завершению самой оболочки, если процесс доставит ей SIGTERM. Соответствующий синтаксис будет выглядеть примерно так:

#!/usr/bin/env bash

# define signal handler
term_handler() {
  echo "bash caught TERM but refuses to terminate"
}

# register signal handler
trap term SIGTERM

# run process that might send a signal
./helloapp

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

Но вы пояснили в комментариях, что вы действительно хотите, чтобы выполнение ./helloapp продолжалось после вызова kill(). Это не то, чего вы можете достичь удаленно с помощью ловушки в оболочке, которая запускает процесс. Ловушка обрабатывает сигналы, передаваемые самой оболочке, а не любому другому процессу.


Что вы можете сделать вместо

Итак, чтобы быть ясным, причина того, что ваш процесс, похоже, не проходит дальше kill(), заключается в том, что он сам входит в число процессов, в которые доставляется SIGTERM, и обработка по умолчанию для SIGTERM - это завершение процесса. , Когда он получает свой собственный сигнал, он завершается. У вас есть два варианта, чтобы избежать этого:

  1. Пусть процесс избегает самой сигнализации. Возможные пути здесь

    • пусть он сигнализирует о конкретном процессе, а не обо всех процессах в своей группе процессов

      kill(a_positive_pid_different_from_mine, SIGTERM);
      
    • сделайте так, чтобы он записал свой исходный номер группы процессов, затем поместите себя в новую группу процессов перед тем, как убить исходную группу процессов. Предполагая, что процесс уже не является лидером группы процессов, это может быть:

      pid_t original_pg = getpgid(0);
      setpgid(0, 0);
      kill(-original_pg, SIGTERM);
      
  2. Пусть сам процесс зарегистрирует обработчик для сигнала. Например, это заставит процесс игнорировать следующие SIGTERM полученные:

    struct sigaction action = { .sa_handler = SIG_IGN, .sa_flags = SA_RESETHAND };
    sigaction(SIGTERM, &action, NULL);
    

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

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