【问题标题】:Should I reset termios settings on SIGINT/SIGTERM?我应该重置 SIGINT/SIGTERM 上的 termios 设置吗?
【发布时间】:2018-01-01 05:02:20
【问题描述】:

我在玩termios,我很快发现如果我更改终端设置并退出,我的更改将持续存在并搞砸我的环境。所以我设置我的程序以使用tcgetattr 保存初始设置并在退出前重置它们。

但是,我预测,如果我在程序运行时点击Ctrl-C 发送 SIGINT,这将导致终端仍然有我修改后的设置,因为我的程序不会执行代码将它们重置回旧设置。

但这并没有发生。在 Ubuntu 和 macOS Sierra 中,我的终端设置都被还原,就好像我在程序中重置了它们一样。

所以问题是:我一般可以指望这种行为吗?或者注册信号处理程序以捕获 SIGINT/SIGTERM 并在退出前恢复终端设置是否有意义?

代码

回答这个问题可能不需要看代码,但这里是我的例子,以防你好奇:

#include <stdio.h>
#include <string.h>
#include <termios.h>

int main() {
        // put terminal into non-canonical mode
        struct termios old;
        struct termios new;
        tcgetattr(0, &old);
        new = old;
        new.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(0, TCSANOW, &new);

        // loop: get keypress and display (exit via 'x')
        char key;
        printf("Enter a key to see the ASCII value; press x to exit.\n");
        while (1) {
                key = getchar();
                printf("%i\n", (int)key);
                if (key == 'x') { break; }
        }

        // set terminal back to canonical
        tcsetattr(0, TCSANOW, &old);
        return 0;
}

【问题讨论】:

  • "// 假设 stdin 是文件描述符 0" => 如果 0 不是标准输入,则您的实现不符合 POSIX。
  • 我环顾四周,我只是认为您的外壳重置了属性本身。
  • 我也怀疑。

标签: c signals termios


【解决方案1】:

看到我的 Arch Linux 终端设置也“被还原”,我有点惊讶。但实际上它们保持不变。当我更改您的代码时,我设法跟踪了一些异常情况。

//...
new.c_lflag &= ~(ICANON | ECHO);
new.c_cc[VMIN]  = 0;
new.c_cc[VTIME] = 0;
//...

因此,如果您不按任何按钮,则输出为-1。如果你点击Ctrl-C,重新编译并启动原始程序(从同一个终端),它也会打印-1,所以没有自动重置。

我不知道为什么ECHO 是“隐藏”的,我很想知道,但我建议您手动恢复所有终端设置。

【讨论】:

  • 我无法重现您提到的行为,但如果它可以在任何地方产生,我认为您是对的,注册信号处理程序以重置终端设置是有意义的。最坏的情况是你做一些额外的工作。
猜你喜欢
  • 2012-04-09
  • 2015-10-05
  • 1970-01-01
  • 2011-09-21
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多