djc*_*535 7 shell bash c signals pty
我有一个 C 程序,它使用 forkpty 来执行 bash shell。我发现此 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
}
Run Code Online (Sandbox Code Playgroud)
其他控制字符似乎可以通过,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
Run Code Online (Sandbox Code Playgroud)
SigIgn 设置了 2 位,这意味着 2 (SIGINT) 被忽略。如果我做完全相同的事情,但在标准终端中运行 sleep (或 cat 一个巨大的文件或其他什么),则该位被清除。当我启动 pty bash 并导致它创建忽略 SIGINT 的孙子程序时,我在做什么?
此外,如果我向进程发送 SIGINT 信号
StandardTerm:# kill -2 26611
Run Code Online (Sandbox Code Playgroud)
什么都没发生。奇怪的是,当我向 bash shell 发送相同的命令时,我 forkpty 的它可以工作,因为 bash shell 不会忽略 SIGINT。
也许你只需要这样做:
\n\nstty sane\nRun Code Online (Sandbox Code Playgroud)\n\nI notice that the forkpty() man page says it will copy the termios settings of *termp to the newly opened pty, but it doesn\'t specifically say what it does with these otherwise, and the only not-NULL arg you hand forkpty() is for the pty master fd. I would guess you\'d wind up with an entirely NULL termios structure, which can\'t be very useful. It wouldn\'t bother bash terribly which has got readline() to handle all its own terminal stuff, and so it would interpret all of the default characters by default anyhow.
这是关于该主题的一篇内容丰富的文章的块引用:
\n\n\n\n\n\n
stty\ 的-F选项非常适合查看其他程序正在对其终端执行的操作。如果您在 shell 中运行tty,它将打印该 shell 终端设备的路径(通常采用 的形式/dev/pts/N,至少在 Linux 下是这样)。现在,您可以从不同的 shell 运行stty -a -F /dev/pts/N以查看第一个 shell 的终端是如何配置的。然后,您可以在第一个 shell 中运行程序,并stty在第二个 shell 中重复该咒语以查看设置了哪些设置。例如,如果我stty -F /dev/pts/10现在跑步(当我通过那个 ptybash与某人交谈时gnome-terminal),我会看到:
$ stty -F /dev/pts/10\n speed 38400 baud; line = 0;\n eol = M-^?; eol2 = M-^?; swtch = M-^?; lnext = <undef>; min = 1; time = 0;\n -icrnl iutf8\n -icanon -echo\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n所以我们可以看到它
\nbash/readline禁用了CR\xe2\x86\x92LF输入(icrnl)的翻译,禁用了canonical模式 和echo,但打开了 UTF-8 模式(因为bash检测到了 utf-8 语言环境)。请注意,如果我stty直接在该 shell 中运行,我会看到一些略有不同的内容:
$ stty\n speed 38400 baud; line = 0;\n eol = M-^?; eol2 = M-^?; swtch = M-^?;\n iutf8\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n这是因为
\nbash它维护自己的一组termios设置(对于readline),并保存和恢复正在运行的程序的设置,因此运行程序时的设置与您在提示符下键入时的设置不同bash。