在Linux上,可以以某种方式禁用程序的信号 外部...也就是说,没有修改其源代码?

语境:

我在打电话(还有爪哇)从Linux上的bash脚本中的程序。我不希望我的bash脚本和脚本启动的其他程序(作为前景过程)的任何中断。

虽然我可以使用...

trap '' INT

...在我的bash脚本中禁用CTRL C信号,仅当程序控件恰好在BASH代码中时,这才能起作用。也就是说,如果我在运行C程序时按CTRL 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.

正如评论中的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 钩。这是非验证任务(您必须编译可加载的任务 _init(), sigaction() 内部),所以我不会在此处包含完整的代码。您可以找到一个sigsegv的示例 phack卷0x0b,第0x3A,phile#0x03.

替代,尝试 nohuptail 诡计。

nohup  your_command &
tail -F nohup.out

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

我失败了,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,但我不知道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