从外部禁用Linux程序的信号

在Linux上,是否有可能以某种方式禁用外部程序的信号传输……也就是说,不修改它们的源代码?

语境:

我正在Linux上的bash脚本中调用一个C( 也是一个Java )程序。 我不希望我的bash脚本和脚本启动的其他程序(作为前台进程)有任何中断。

虽然我可以使用…

trap '' INT 

…在我的bash脚本中禁用Ctrl C信号,这只有在程序控制碰巧在bash代码中时才起作用。 也就是说,如果我在C程序运行时按Ctrl C,C程序会中断并退出! 这个C程序正在做一些关键的操作,因为我不希望它被打断。 我没有访问这个C程序的源代码,所以在C程序里面的信号处理是没有问题的。

 #!/bin/bash trap 'echo You pressed Ctrl C' INT # AC 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: yc # To build: gcc -oy yc # # #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

由于注释中的ephemient笔记,信号处置也是继承,所以你可以让包装忽略信号,而不是阻止它:

 #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; } 

(当然,对于腰带和大括号的方法,你可以做到这一点)。

“陷阱”命令是本地进程,不适用于儿童。

要真正捕获信号,你必须使用LD_PRELOAD钩子来破解它。 这是非trival任务(你必须用_init()sigaction()内部编译一个可加载的),所以我不会在这里包含完整的代码。 您可以在Phack Volume 0x0b,Issue 0x3a,Phile#0x03上找到SIGSEGV的示例。

换句话说,尝试nohuptail技巧。

 nohup your_command & tail -F nohup.out 

我建议您的C(和Java)应用程序需要重写,以便它可以处理异常,如果确实需要中断,断电等情况会发生什么情况。

我失败了,歼十六是对的。 用户是否需要与流程进行交互,或只是看到输出(他们是否需要查看输出?)

上面解释的解决方案并不适用于我,甚至连接Caf提出的两个命令。

但是,我终于成功地获得了预期的行为:

 #!/bin/zsh setopt MONITOR TRAPINT() { print AAA } print 1 ( ./child & ; wait) print 2 

如果在child运行时按下Ctrl-C,它将等待退出,然后打印AAA和2. child不会收到任何信号。

子shell用于防止显示PID。

对不起…这是为zsh,虽然问题是为bash,但我不知道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