【问题标题】:C program - Process don't invoke after sending SIGTERM signalC程序-发送SIGTERM信号后不调用进程
【发布时间】:2020-04-27 00:41:04
【问题描述】:

我是 C 编程中使用信号的新手。

为了演示我的问题,我写了两个简单的源代码 child.c 和 parent.c。

child.c

void errorHandler(char* message);
void sigterm_handler(int signum, siginfo_t* info, void* ptr);

int main(){

    struct sigaction action1;
    memset(&action1, 0, sizeof(action1));
    action1.sa_sigaction = sigterm_handler;
    action1.sa_flags = SA_SIGINFO;

    if(sigaction(SIGTERM, &action1, NULL) != 0)
        errorHandler("Signal sigterm_handler registration failed");

    for(int i = 0; i < 10; i++){

        printf("%d\n", i);
        if(i == 5){

            if(raise(SIGSTOP)!= 0)
                errorHandler("Raise SIGSTOP failed");
        }
    }

    return EXIT_SUCCESS;
}

void errorHandler(char* message){

    printf("Error: %s: %s\n", message, strerror(errno));
    exit(EXIT_FAILURE);
}

void sigterm_handler(int signum, siginfo_t* info, void* ptr){

    printf("Child: Process %d finishes\n", getpid());
    exit(EXIT_SUCCESS);
}

父.c

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

    int status;
    pid_t mem;
    pid_t child = fork();

    if(child == 0){

        char* arr[] = {"./child", NULL};
        execv(arr[0], arr);
    }

    else if(child > 0){

        mem = child;
        waitpid(mem, &status, WUNTRACED);
    }

    if(WSTOPSIG(status)){

        printf("Sending SIGTERM to child\n");
        kill(mem, SIGTERM);
        waitpid(mem, &status, 0);
    }

    return 0;
}

当我运行 parent.c 时,程序打印到标准输出:

1
2
3
4
5
Sending SIGTERM to child

但随后程序卡住了,可能是因为 sigterm_handler 没有调用,而不是打印“子:进程 *** 完成”。

我尝试阅读 linux 手册页,但仍然无法弄清楚。

谁能给我解释一下是什么导致了这个问题?

任何答案将不胜感激!

【问题讨论】:

  • printf 不是信号安全函数。
  • @Someprogrammerdude 但这确实意味着它可能不会在信号处理程序中使用。您只需确保在同一流上运行的其他 stdio 函数不会被该信号处理程序中断。
  • @Ctx no, printf 永远不能在信号处理程序中使用。只是为了开始,printf 可以调用malloc,它本身不是信号安全的,并且可以在退出时刷新 stdio 缓冲区时调用信号处理程序。甚至 snprintfdprintf 都不能安全地从信号处理程序中使用。
  • 不,exit(3) 也不能从信号处理程序中调用。只有_exit(2) 是信号安全的,但这可能会在printf 消息实际打印出来之前终止进程;-)
  • @mosvy 这是不正确的,当调用非异步安全函数并在信号处理程序中使用类似 printf() 时,在主程序中阻止信号传递是一个有效的选项。

标签: c signals fork wait


【解决方案1】:

问题是,子进程调用

if(raise(SIGSTOP) != 0)

还在停止,当父级在这里时

kill(mem, SIGTERM);

发送信号SIGTERM。信号不会丢失,但仍会在子进程中挂起,并将在进程继续运行时被传递。您可以通过发出

kill(mem, SIGCONT);

直接在发送SIGTERM 之后。然后,子进程将继续运行,将传递信号并执行处理程序,打印诊断消息并退出进程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多