使用forkpty()创建了一个bash shell。似乎这个shell启动时启动的程序忽略了SIGINT。为什么?

时间:2015-11-09 16:21:52

标签: c linux bash shell pty

我有一个使用forkpty来执行bash shell的C程序。我发现这个shell启动的程序是在忽略SIGINT的情况下启动的,所以当我向shell发送一个Ctrl-C时,它们永远不会关闭。

示例:

int masterFd;
char* args[] = {"/bin/bash", "-i", NULL };
int procId = forkpty(&masterFd, NULL, NULL,  NULL);
if( procId == 0 ){
  execve( args[0], args, NULL);
}
else {
   // Simple code that reads from standard in and writes to masterFd.  
   // I also register for Ctrl-C and write it to masterFd if caught
}

其他控制字符似乎可以通过,ctrl-D,ctrl-?但是,每当我查看新bash shell启动的进程的状态时,就会看起来SIGINT被屏蔽掉了。

MyShell:# sleep 1000

StandardTerm:#  ps -ef | grep sleep
root    26611  19278  0  17:44  pts/1   00:00:00 sleep 1000
root    26613  32376  0  17:44  pts/1   00:00:00 grep sleep

StandardTerm:# grep Sig proc/26611/status
SigQ:    0/256428
SigPnd:  0000000000000000
SigBlk:  0000000000000000
SigIgn:  0000000000010006   <- THE 6 IS THE PROBLEM
SigCgt:  0000000180000000

SigIgn具有2位设置,这意味着忽略2(SIGINT)。如果我做同样的事情,但在标准终端中运行睡眠(或猫一个巨大的文件或其他),这个位被清除。当我启动我的pty bash导致它创建忽略SIGINT的孙子程序时,我在做什么?

此外,如果我向进程发送SIGINT信号

StandardTerm:# kill -2 26611
没有任何反应。奇怪的是,当我向bash shell发送相同的命令时,我运用了它,因为bash shell不会忽略SIGINT。

提前致谢!

2 个答案:

答案 0 :(得分:0)

父进程是否已屏蔽SIGINT

fork()execve()都将信号掩码传播到子procs,也许就是这种情况?

答案 1 :(得分:0)

查看 termios(3)手册页。您使用&#39; NULL &#39;作为 forkpty 调用中的 termios (第三个)参数,意味着&#39; c_iflag &#39; termios 结构值将是未定义的,并且继承其父进程的值。 (谢谢你@ djc6535)

pid_t forkpty(int *amaster, char *name,
              const struct termios *termp,
              const struct winsize *winp);

struct termios
  {
    tcflag_t c_iflag;       /* input mode flags */
    tcflag_t c_oflag;       /* output mode flags */
    tcflag_t c_cflag;       /* control mode flags */
    tcflag_t c_lflag;       /* local mode flags */
    cc_t c_line;            /* line discipline */
    cc_t c_cc[NCCS];        /* control characters */
    speed_t c_ispeed;       /* input speed */
    speed_t c_ospeed;       /* output speed */
  };

来自 termios(3)手册页:

    c_iflag flag constants:

    IGNBRK Ignore BREAK condition on input.

    BRKINT If IGNBRK is set, a BREAK is ignored.  If it is not set but BRKINT is set, then a  BREAK  causes  the  input  and  output
           queues to be flushed, and if the terminal is the controlling terminal of a foreground process group, it will cause a SIG‐
           INT to be sent to this foreground process group.  When neither IGNBRK nor BRKINT are set, a BREAK reads as  a  null  byte
           ('\0'), except when PARMRK is set, in which case it reads as the sequence \377 \0 \0.

相关部分是&#39; 当既没有设置IGNBRK也没有设置BRKINT时,BREAK读取为空字节(&#39; \ 0&#39;)

所以一切都按预期工作。

也许建立一个 termios 结构来设置各种重要的标志?