[英]Why the signal handler doesn't process the signal
我正在尝试制作一个模拟命令nohup的程序。 该程序将作为要执行的命令的名称作为第一个参数。 当终端关闭时,不得通知我的程序执行的程序,它将不得不忽略SIGHUP。 如果我使用以下命令测试程序:
./mynohup sleep 120 &
然后,我尝试从另一个终端发送一个SIGHUP,当它应该不受睡眠时,睡眠终止。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include "utils.h"
#define NOHUP_OUT_FILE "nohup.out"
static void handle_signal(int signum)
{
if(signum == SIGHUP)
{
printf("This is ignored\n");
}
else
{
printf("Not ignored\n");
}
fflush(stdout);
}
/* configure handlers */
static void set_signals(void)
{
struct sigaction sa;
int rc;
/* TODO - ignore SIGHUP */
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = handle_signal;
rc = sigaction(SIGHUP, &sa, NULL);
DIE(rc == -1, "sigaction");
}
/* execute a new program */
static void exec_func(int argc, char **argv)
{
int rc;
int i;
char **exec_args;
int fd;
set_signals(); /* ignore SIGHUP */
if(isatty(STDOUT_FILENO))
{
fd = open(NOHUP_OUT_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
DIE(fd < 0, "open");
dup2(fd, STDOUT_FILENO);
close(fd);
}
/* exec a new process */
exec_args = malloc(argc * sizeof(*exec_args));
DIE(exec_args == NULL, "malloc");
for (i = 0; i < argc-1; i++)
exec_args[i] = argv[i+1];
exec_args[argc-1] = NULL;
execvp(exec_args[0], exec_args);
DIE(1, "execvp");
}
int main(int argc, char **argv)
{
if (argc <= 1) {
fprintf(stderr, "Usage: %s command_and_arguments\n", argv[0]);
exit(EXIT_FAILURE);
}
exec_func(argc, argv);
return 0;
}
我试图跳过创建新进程的过程,并且信号处理程序运行良好。 如果信号处理程序具有以下格式,则程序可以运行
static void set_signals(void)
{
struct sigaction sa;
int rc;
/* ignore SIGHUP */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_IGN;
rc = sigaction(SIGHUP, &sa, NULL);
DIE(rc == -1, "sigaction");
}
我不明白为什么当我创建信号处理程序的第一个版本时该程序不起作用,而在第二个版本中它却起作用。
提前致谢!
所有exec函数将捕获的信号的处理方式重置为其默认处理方式。
执行时,过程映像将被破坏,并由新程序的过程映像替换。 在其中,指向传递给sigaction的handle_function
的指针不再具有含义,或者至少不再具有旧含义。 唯一明智的操作系统可以处理的信号时做execve
是将它们重置。
SIG_IGN
的含义是通用的,独立于当前程序,这就是SIG_IGN
可以被继承的原因。
execvp()
是execve()
系统调用的前端。
除以下内容外,所有进程属性均在execve()期间保留:
* The dispositions of any signals that are being caught are reset to the default (signal(7)).
因此,您安装的信号处理程序将重置。
nohup(1)
程序只是将progran名称( nohup
)及其选项从argc
/ argv
参数转移到main
,将stdout
/ stderr
重定向到文件( nohup.out
),以防一个或两个都指向一个文件。 tty设备,然后忽略SIGHUP
和execvp(*argv, argv);
供原始程序执行。 它甚至根本不提供fork(2)
。
FreeBSD nohup的源代码在这里 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.