Вопрос

На Linux можно ли каким -то образом отключить сигнализацию для программ внешне... То есть без изменения их исходного кода?

Контекст:

Я звоню в C (а также Java) Программа из сценария Bash на Linux. Я не хочу никаких прерываний для моего сценария Bash, а также для других программ, которые запускает скрипт (в качестве процессов переднего плана).

Пока я могу использовать ...

trap '' INT

... В моем скрипте Bash, чтобы отключить сигнал Ctrl C, это работает только тогда, когда управление программой оказывается в коде Bash. То есть, если я нажимаю CTRL C во время работы C -программы, программа C прерывается и выходит! Эта программа C выполняет некоторую критическую работу, из -за которой я не хочу, чтобы ее прервали. У меня нет доступа к исходному коду этой программы C, поэтому обработка сигналов внутри программы C не может быть сомнена.

#!/bin/bash

trap 'echo You pressed Ctrl C' INT 

# A C program to emulate a real-world, long-running program,
# which I don't want to be interrupted, and for which I 
# don't have the source code!
#
# File: y.c
# To build: gcc -o y y.c
#
# #include <stdio.h>
# int main(int argc, char *argv[]) {
#  printf("Performing a critical operation...\n");
#    for(;;); // Do nothing forever.
#  printf("Performing a critical operation... done.\n");
# }

./y

С уважением,

/Hs

Это было полезно?

Решение

Маска сигнала процесса наследуется через exec, так что вы можете просто написать небольшую программу обертки, которая блокирует SIGINT и выполняет цель:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        sigset_t sigs;

        sigemptyset(&sigs);
        sigaddset(&sigs, SIGINT);
        sigprocmask(SIG_BLOCK, &sigs, 0);

        if (argc > 1) {
                execvp(argv[1], argv + 1);
                perror("execv");
        } else {
                fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
        }
        return 1;
}

Если вы собираете эту программу noint, вы бы просто выполнили ./noint ./y.

Как отмечает эфемиенты в комментариях, характеристика сигнала также наследуется, поэтому вы можете, чтобы обертка игнорировала сигнал вместо блокировки:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        struct sigaction sa = { 0 };

        sa.sa_handler = SIG_IGN;
        sigaction(SIGINT, &sa, 0);

        if (argc > 1) {
                execvp(argv[1], argv + 1);
                perror("execv");
        } else {
                fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
        }
        return 1;
}

(И, конечно же, для подхода к ремням и бречкам, вы можете сделать и то, и другое).

Другие советы

Команда «Trap» является локальной для этого процесса, никогда не применяется к детям.

Чтобы действительно поймать сигнал, вы должны взломать его, используя LD_PRELOAD крюк. Это не тривенная задача (вы должны скомпилировать нагрузку с _init(), sigaction() Внутри), поэтому я не буду включать полный код здесь. Вы можете найти пример для Sigsegv на Том Phack 0x0b, выпуск 0x3a, Phile #0x03.

Альтернативно, попробуйте nohup а также tail обманывать.

nohup  your_command &
tail -F nohup.out

Я бы предположил, что ваш приложение C (и Java) нуждается в переписывании, чтобы оно могло справиться с исключением, что произойдет, если его действительно нужно прервать, сбой мощности и т. Д.

I, который терпит неудачу, J-16 прямо на деньгах. Нужно ли пользователю взаимодействовать с процессом или просто видеть вывод (им даже нужно увидеть выход?)

Решения, объясненные выше, не работают для меня, даже путем цепочки обе команды, предложенные CAF.

Тем не менее, мне наконец -то удалось получить ожидаемое поведение таким образом:

#!/bin/zsh
setopt MONITOR
TRAPINT() { print AAA }

print 1
( ./child & ; wait)
print 2

Если я нажму ctrl-c, пока child работает, он будет ждать, что он выходит, затем напечатает AAA и 2. child не будет получать никаких сигналов.

Подборная используется для предотвращения показа PID.

И извините ... это для ZSH, хотя вопрос для Bash, но я недостаточно знаю, чтобы обеспечить эквивалентный сценарий.

Это пример кода включения сигналов, таких как Ctrl+C для программ, которые блокируют его.

fixcontrolc.c

#include <stdio.h>
#include <signal.h>
int sigaddset(sigset_t *set, int signo) {
    printf("int sigaddset(sigset_t *set=%p, int signo=%d)\n", set, signo);
    return 0;
}

Составьте это:

gcc -fPIC -shared -o fixControlC.so fixControlC.c

Запустить его:

LD_LIBRARY_PATH=. LD_PRELOAD=fixControlC.so mysqld
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top