【问题标题】:Chaining signal handlers in ncurses在 ncurses 中链接信号处理程序
【发布时间】:2021-02-07 17:31:42
【问题描述】:

我的 Ncurses 应用程序正在循环输入键盘并将输出打印到屏幕上。当我停止我的应用程序 (ctrl+z) 并稍后恢复它时,我注意到输入缓冲区有时包含不需要的字符。所以我想用flushinp()来丰富ncurses默认提供的SIGCONT处理程序,简化代码如下:

#include <csignal>
#include <curses.h>
#include <stdlib.h>
#include <fstream>

struct sigaction oldact, newact;
extern "C" void sigContHandler(int sig)
{
    std::ofstream of("sc", std::ofstream::app);
    of << "Handling cont " << std::endl;
    flushinp();
    //Call old handler, but crash as it is always 0
    (oldact.sa_handler)(sig);
}

    int main(void)
    {
        initscr();
        cbreak();
        noecho();
        clear();

        newact.sa_handler = sigContHandler;
        newact.sa_flags = 0;
        sigemptyset (&newact.sa_mask);
        sigaction(SIGCONT, &newact, &oldact);

        int c = 0;
        while (c = getch()) {
            if (c == 'q')
                break;
            mvaddch(0, 0, c);
        }
    refresh();
    endwin();
    exit(0);
}

我不能调用旧的 SIGCONT 处理程序,因为它始终为 0。显然,如果我不向链信号处理程序添加代码,则会成功调用此默认处理程序。我不明白为什么我不能调用旧处理程序,我做错了什么?

【问题讨论】:

  • 是什么阻止您在调用sa_handler 之前检查它是否为NULL?这是系统在尝试调用处理程序之前会执行的操作。

标签: c++ signals ncurses


【解决方案1】:

我在flushinp 的文档中没有发现任何表明它是信号安全的。由于信号是什么以及它们是如何工作的,默认情况下,任何库函数(尤其是第三方库)都被默认假定为 非信号安全,除非另有说明.因此,它们不能从异步信号处理程序中调用。

请注意,例如,signal-safety(7) manual page 明确枚举唯一的信号安全的 C 库函数。除非该函数在列表中,否则不能从信号处理程序调用它。 C++ 库类、模板和函数都不是信号安全的。

如果您的所有信号处理程序都被称为原始处理程序(如果它不是 NULL,并且如果它是 NULL 则什么也不做),那就没问题了。但是flushinp 的调用引入了未定义的行为,这就是行的结尾。

在 Linux 上安全地执行此操作的唯一方法是使用 a signal file descriptor,有效地将异步信号处理程序转换为文件描述符事件,并为标准输入和信号文件实现多路复用非阻塞 poll 循环描述符,与 curses 库集成。这是相当复杂的,并且需要相当多的工作。也不清楚您不需要的输入的来源是什么。输入不是凭空产生的,因此肯定有其原因,您可能希望首先朝那个方向看,而不是试图解决结果而不是原因。

【讨论】:

  • 当我的处理函数除了 '(oldact.sa_handler)(sig);' 之外没有其他任何东西时问题依然存在
  • 我在“if not NULL”部分指出了这一点。根本没有“老处理程序”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-02
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 2017-11-13
相关资源
最近更新 更多