我建立了以下信号处理程序:
void sig_handler(int sig)
{
if (sig == SIGINT)
{
printf("\n");
rl_on_new_line();
rl_replace_line("", 0);
rl_redisplay();
}
}
在 readline 提示符下效果很好,但如果我运行阻塞命令(比如
cat
),提示符会在同一行上打印两次。
如果我删除
rl_redisplay();
,它会在运行 cat
时起作用,但当 readline()
等待输入时,永远不会打印提示。我已阅读this问题,并且SA_RESTART
设置在sa.sa_flags
中。
您无法在信号处理程序中安全地执行此操作。 您看到的任何这样做的代码示例都只是简单的错误。
根据 C11 标准(草案)第 4 段7.1.4 使用库函数:
标准库中的函数不保证可重入,并且可能会修改具有静态或线程存储持续时间的对象。如
脚注188所述:
因此,信号处理程序通常不能调用标准库函数。因此,从信号处理程序中调用任何 C 标准函数(例如
printf()
)都是不安全的。但是
POSIX 允许从信号处理程序中进行 some 调用:
...不在该表上,则无法从信号处理程序中安全地调用它。...
如果信号处理程序引用除 errno 之外的具有静态存储持续时间的任何对象,而不是通过为声明为 volatile 的对象赋值,
sig_atomic_t
,或者如果信号处理程序调用任何函数,则行为未定义除下表中列出的功能之一之外,本标准中定义了。 下表定义了一组异步信号安全的函数。因此,应用程序可以不受限制地从信号捕获函数中调用它们。如果调用的函数
Linux 的详细信息可以在 Linux
signal-safety
手册页:
中找到async-signal-safe
函数是可以安全调用的函数 从信号处理程序内部。 许多函数做的是设置一个标志,以便在进程退出时重新打印提示:不异步信号安全。 特别是,不可重入函数通常是 从信号处理程序调用不安全。 导致函数不安全的问题类型可以很快被解决 当人们考虑 stdio
的实现时就可以理解 库,其所有函数都不是异步信号安全的。您
可以
volatile sig_atomic_t reprintPrompt = 0;
void sig_handler(int sig)
{
if (sig == SIGINT)
{
reprintPrompt = 1;
}
}
...
int main(int argc, char **argv)
{
...
if (reprintPrompt)
{
printf("\n");
rl_on_new_line();
rl_replace_line("", 0);
rl_redisplay();
}
return(0);
}