【问题标题】:Returning from Signal Handlers从信号处理程序返回
【发布时间】:2012-01-08 09:43:58
【问题描述】:

我没有以正确的方式离开我的信号处理函数吗?它似乎没有正常返回程序。相反,它进入循环并在应该等待用户输入的地方,它跳过并将“用户输入”的长度读取为 -1 并出错。 (在代码中会更有意义。)

void handle_SIGINT() {

    int k = recent;
    int count = 0;
    int stop;

    if (stringSize >= 10) {
        stop = 10;
    }
    else {
        stop = p;
    }

    printf("\nCommand History:\n");

    for (count = 0; count < stop; count++) {

        if (k < 0) {
            k += 10;
        }
        printf("%s", string[abs(k)]);
        k -= 1;

    }

}



void setup(char inputBuffer[], char *args[],int *background)
{
    //char inputBuffer[MAX_LINE];
    int length, /* # of characters in the command line */
    i,      /* loop index for accessing inputBuffer array */
    start,  /* index where beginning of next command parameter is */
    ct;     /* index of where to place the next parameter into args[] */
    int add = 1;
    ct = 0;

    /* read what the user enters on the command line */
    length = read(STDIN_FILENO, inputBuffer, MAX_LINE);  


        printf("%i",length);
    start = -1;
    if (length == 0)
        exit(0);            /* ^d was entered, end of user command stream */
    if (length < 0){
        perror("error reading the commanddddddddd");
        exit(-1);           /* terminate with error code of -1 */
    }
}



int main(void)
{
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
    int background;             /* equals 1 if a command is followed by '&' */
    char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */
    FILE *inFile = fopen("pateljay.history", "r");



    if (inFile != NULL) {
        int count = 0;
        char line[MAX_LINE];
        while (fgets(line,sizeof line, inFile) != NULL) {
            string[count] = strdup(line);
            //string[count][strlen(line)] = '\n';
            //string[count][strlen(line) + 1] = '\0';
            printf("%s", string[count]);
            count++;
            stringSize++;
        }


            p = count % 10;
            recent = abs(p - 1);

    }   

    fclose(inFile); 

    /* set up the signal handler */
    struct sigaction handler;
    handler.sa_handler = handle_SIGINT;
    sigaction(SIGINT, &handler, NULL);

    while (1) {/* Program terminates normally inside setup */


        background = 0;
        printf("COMMAND->");

        fflush(0);

        setup(inputBuffer, args, &background);/* get next command */
    }
}

所以当输入 ctrl+c 时,它应该捕获信号并处理它。一旦它返回到 main,它就会进入 setup 并完全跳过 read 函数并使长度等于 -1。这反过来又使程序出错。我认为 handle_SIGINT 中的代码与现在一样无关紧要。有谁知道为什么它会在设置中跳过读取功能?

【问题讨论】:

  • 您不能在信号处理程序中使用 printf()。
  • 当我运行它时它似乎工作,但我认为你是对的。我只是不知道用什么来代替它,因为我对 C 不是很熟悉。
  • 关于printf 问题,在信号处理程序中使用时,请参阅此问答:stackoverflow.com/questions/2461583/…
  • @Tom:因为它不是可重入的。 (printf 可能会调用 malloc 来获取缓冲区空间,并且由于它是从信号处理程序中调用的,因此可能会中断 malloc。也许 stdio 的内务处理也可能会在中断时变得混乱)
  • 从信号处理程序中获取printf 是一个非常棘手的问题。有关一些解决方案,请参阅osiris.978.org/~alex/safesignalhandling.html

标签: c signal-handling


【解决方案1】:

信号处理程序应该接受一个 int 参数:

void handle_sigint(int signum) {}

【讨论】:

    【解决方案2】:

    read 正在阻塞,等待输入。 SIGINT 到达。内核调用您的信号处理程序。当您的信号处理程序返回时,内核使read 返回-1 并将errno 设置为EINTR。您需要再次调用read 来检查并处理这种情况:

       do {
            length = read(STDIN_FILENO, inputBuffer, MAX_LINE);
       } while (length == -1 && errno == EINTR);
    

    【讨论】:

    • errno 是否由内核为所有程序定义?
    • 顺便说一句,除了在玩具程序中,我永远不会使用这个解决方案,因为它不能解决从信号处理程序调用printf 的问题,这是被禁止的。在一个严肃的程序中,我会使用 self-pipe 技巧。
    • 你需要#include &lt;errno.h&gt;才能得到errno的正确定义。
    • 好的,非常感谢,特别是关于信号处理程序的额外信息。我查找了自管技巧,可能会尝试一下。还发现了一些关于 pselect 的信息。不确定 select 究竟做了什么,我是否应该将它包含在我的 while 循环中以使信号处理程序返回那里?
    • 我会推荐 poll 而不是 select,因为 poll 的界面更简单。对于任何一个,此页面可能有用:publib.boulder.ibm.com/infocenter/iseries/v6r1m0/…
    猜你喜欢
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    相关资源
    最近更新 更多