【问题标题】:Catching signal SIGINT still kills the program捕获信号 SIGINT 仍然会杀死程序
【发布时间】:2013-11-05 21:41:33
【问题描述】:

我正在编写自己的迷你 bash,我想禁用默认的 SIGINT 行为(只有“退出”应该终止 bash)但 SIGINT 可能会杀死正在运行的孩子(例如运行“睡眠 60 | 睡眠 30”)。

为了捕捉 SIGINT,我使用了signal(SIGINT, catchSignal); 函数。问题是在我的 minibash 中发送 ^C 仍然会杀死它 =(

根据 GNU:http://www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html

编辑:也许值得一提的是,它在 Mac 上按预期工作,而不是在 Linux 上!

A signal handler is just a function that you compile together with the rest of the program. Instead of directly invoking the function, you use signal or sigaction to tell the operating system to call it when a signal arrives.

所以我明白,当我按下 ^C 时,我的 catchSignal() 将被执行,但除此之外什么都没有。对吧?

如果是,那么为什么我的 minibash 会终止,这就是我的 catchSignal()。它确实有kill(),但仅适用于奔跑的孩子。

示例执行

[22:33:31][user][~/edu/sysprog/lab4]$ ./minibash 
mbash% ^CCatched Sigint
Inside Sigint
No children

代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

#include "sighant.h"

// Global variable
extern pidList children;

void catchSignal(int recvSign)
{
    printf("Catched Sigint\n");
    if(recvSign == SIGINT)
    {
        printf("Inside Sigint\n");
        if(children.count < 1)
        {
            printf("No children\n");
        }

        for(int i = 0; i < children.count; i++)
        {
            if(children.child[i] >= 0)
            {
                printf("KILLIN\n\n");
                kill(children.child[i], SIGKILL);
            }
        }
    }
    else
    {
        fprintf(stderr, "[ERROR] Could not execute Signal! (reason uknown)");
    }
}

CODE2

int main(void)
{

    fprintf(stderr, "mbash%% ");
    fflush(stderr);

    signal(SIGINT, catchSignal);

    .......

【问题讨论】:

  • 你能展示其余的主要内容吗?一切似乎都很好,也许你的 mbash 结束了,因为它无事可做?您还可以检查 signal() 是否正常工作,这是一个很好的例子:link 或者尝试捕获其他信号(如 USR1),从其他控制台发送它,看看会发生什么。
  • 你的孩子怎么样? pthreads或只是分叉?编辑:如果你用kill 杀死它们,可能不是 pthreads。分叉和信号处理并非易事。
  • 你的 mini shell 的退出代码应该知道它是否被信号终止,如果是,由哪个信号终止。
  • 是的@DarthHunterix。紧随其后的是while(fgets(...,stdin)!= NULL)。出于某种原因,这个信号(); catch 将 NULL 发送到标准输入,因此我的程序只是终止执行。不知道为什么会这样。也许我必须通过将“0”推到标准输入或其他东西来破解它。
  • 最好添加一个条件,如“((fgets(...,stdin)!= NULL)||中断))。如果检测到中断,您只需忽略NULL并恢复正常处理。无论如何,我有点陌生,所以请不要介意我问这个问题:我的评论算作答案吗?

标签: c linux signals


【解决方案1】:

我建议在建立信号处理程序后添加siginterrupt(SIGINT, 0);,并阅读有关中断系统原语与signal(3) 的对比。

【讨论】:

  • 你能详细说明一下吗?我也遇到了这个问题。