我的信号处理程序出了什么问题?

时间:2014-12-22 01:24:14

标签: c linux signals

在过去几天我写的一个程序遇到了一些困难。我只是想让一个程序与信号一起运行。当用户点击控件c时,我创建了两个管道和一个有两个子节点的父节点。

当用户从子进程中命中控件Z时,我希望孩子们彼此交谈。目前,我只是希望它打印出一些到终端的线路。在对问题进行一些测试之后,我总结了一些因素。

  1. 如果控件Z的信号放在父进程中(代码中注释掉的行),程序运行正常......
  2. 如果信号随后被移动到子进程....它会因某种原因终止程序。我认为这是孩子死亡,但是使用睡眠和等待等命令证明是无效的。
  3. 有人能看到我出错的地方......它真的开始让我烦恼:/

      #include <stdio.h>
        #include <signal.h>
        #include <fcntl.h>
        #include <unistd.h>
        #include <time.h>
        #include <string.h>
    
        pid_t forkA, forkB;
    
        void handleSignal();
        void controlC();
        void controlZ();
    
        int main ()
        {
            signal(SIGINT, handleSignal);
            while(1);
        }    
    
        void handleSignal (int signal)
        {
          if (signal == SIGINT)
            {
              write(1, "ContrlC \n", 11);
            controlC();
            }
          else if (signal == SIGTSTP)
            {
              write(1, "CONTROLZ \n", 11);
              controlZ();
            }
          else
          {
            write(2, "error \n", 8);
          }
        }
    
        void controlC()
        {   
            int firstPipe[2];
            int secondPipe[2];
    
            if (pipe(firstPipe) < 0)
            {
                    write(1,"Error \n", 7);
            }   
            else if (pipe(secondPipe) < 0)
            {
                    write(1,"Error creating pipe 2 \n", 23);
            }
            else
            {
                write(1, "Pipe creations: DONE \n", 22);
            }
    
            //make child
            forkA = fork();
            if (forkA < 0)
            {
                write(2, "FORK ERROR. \n", 13);
            }
            else if (forkA == 0)
            {
                    write(1, "CHILD 1 \n", 9);
                    close(firstPipe[0]);    //close reading end of pipe 1
                    close(secondPipe[1]);//close writing end of pipe 2
                sleep(5);
            }
            else
            {
                forkB = fork();
                    if (forkB < 0)
                    {
                    write(2, "FORK ERROR. \n", 12);
                    }
                else if (forkB == 0)
                {
                signal(SIGTSTP, handleSignal);
                    write(1, "CHild 2 \n", 9);
                    close(firstPipe[1]); //close write end of pipe 1
                        close(secondPipe[0]); //close read end of pipe 2
                sleep(5);
                }
                else
                {
                //signal(SIGTSTP, handleSignal);
    signal(SIGCHLD, SIG_IGN);
                write(1,"parent of both \n", 16);
                wait();
                }
            }               
        }
    
        void controlZ()
        {
            write(1, "woo z \n", 7);
        }
    

3 个答案:

答案 0 :(得分:1)

来自signal(7)

信号处理是每进程属性

因此,这意味着您必须在所有分叉进程中定义信号行为。否则ctrl + c将终止进程或ctrl + z将停止进程。您不必明确SIG_IGN SIGCHLD,因为这是SIGCHLD的默认行为。

在不相关的说明中:请不要使用write(2)将文本输出到终端。使用fprintf(3)。如果要输出到stdout和stderr以输出错误消息,请使用stdout作为第一个参数。这样你就不必担心计算要写的字符数量。

您的等待调用也是错误的,它需要一个int *参数或至少一个NULL参数。

答案 1 :(得分:0)

write(1, "ContrlC \n", 11);write(1, "CONTROLZ \n", 11);肯定是错误的长度。

建议采用不同的方法来避免计算错误,例如

#define CONTORLC "ContrlC \n"
write(1, CONTORLC, sizeof(CONTORLC) - 1);

void write_string(int handle, const char *s) {
  write(handle, s, strlen(s));
}

虽然这会通过避免访问数组边界之外的内存来处理生成的UB,但可能还会存在其他问题。

答案 2 :(得分:0)

信号处理程序应尽可能快地保留。此外,您应该查看question来处理signal(2)sigaction(2)之间的区别。

您是否只是尝试使用USR1USR2以便不破坏sigint / sigcont的语义?