Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何避免信号处理器中的竞争条件_C_Concurrency_Signals_Race Condition - Fatal编程技术网

C 如何避免信号处理器中的竞争条件

C 如何避免信号处理器中的竞争条件,c,concurrency,signals,race-condition,C,Concurrency,Signals,Race Condition,我正在从事一个涉及信号驱动I/O的项目,该项目最终可能会使用使用sigaction()创建的信号处理程序。我担心处理程序可能会被调用多次。换句话说,当它被消息B中断并开始处理B时,它将处理消息A,这可能会导致问题。我在网上看到一些代码使用sigprocmask来避免这种情况,但我觉得这是错误的。例如: void handle_signal(int sig_num) { sigset_t mask_set; /* used to set a signal masking set. */

我正在从事一个涉及信号驱动I/O的项目,该项目最终可能会使用使用sigaction()创建的信号处理程序。我担心处理程序可能会被调用多次。换句话说,当它被消息B中断并开始处理B时,它将处理消息A,这可能会导致问题。我在网上看到一些代码使用sigprocmask来避免这种情况,但我觉得这是错误的。例如:

void handle_signal(int sig_num)
{
    sigset_t mask_set;  /* used to set a signal masking set. */
    sigset_t old_set;   /* used to store the old mask set.   */

    /* re-set the signal handler again to catch_int, for next time */
    signal(SIGINT, catch_int);
    /* mask any further signals while we're inside the handler. */
    sigfillset(&mask_set);
    sigprocmask(SIG_SETMASK, &mask_set, &old_set);

    .... (content handling code here) ....

    /* restore the old signal mask */{{/COMMENT_FONT}*/
    sigprocmask(SIG_SETMASK, &old_set, NULL);
}
这显然是错误的,因为sigprocmask不是信号的原子。换句话说,在调用信号处理程序和调用sigprocmask之间有一个时间窗口,可以在该窗口中第二次或第三次调用信号处理程序,从而创建竞争条件

我的选择:

(1) 使用处理程序内部的信号量将处理程序的任何冗余调用排队

(2) 将处理程序编写为可重入程序,因此可以同时多次调用它

(3) 还有别的解决办法吗


如果我选择上面的选项(2),我能认为套接字读队列是线程安全的吗?例如,假设套接字处理程序被调用两次。实例A开始从套接字读取数据,然后中断,实例B开始读取数据包。这是否会导致A发现队列为空并结束,或者我将面临某种错误的风险?

如果您正在使用
sigaction
设置信号处理程序,则导致触发处理程序的信号默认情况下已在处理程序内被阻止

在您的代码中,所有信号的阻塞和旧掩码的恢复都是关于阻塞所有其他信号,原始信号(触发处理程序)将被阻塞,直到您从处理程序返回(或者您明确地取消阻塞)

使用
sigaction
可以通过设置
struct sigaction
sa_mask
字段来避免执行此块并在处理程序中还原,该字段是处理程序中阻止的信号集

此外,您使用
signal
来“重新设置”处理程序有点混乱,您调用函数
handle\u signal
,然后重新设置为
catch\u int
(假设此处理程序实际处理
SIGINT

每次触发处理程序时,旧的
signal
API确实用于将信号处理程序重置回默认值。但是,默认情况下
sigaction
不执行此操作,因此您不需要“重新设置”如果您使用的是
sigaction
API,则使用信号处理程序。我个人会避免在同一个程序中混合调用
signal
sigaction
,我会选择一个并坚持使用它


总之,我认为您对
sigprocmask
不具有原子性的担忧是不必要的,因为所讨论的信号已经被阻止,您对
signal
sigaction
的混合使用更让我担心。

您的意思是
sigaction()
用于设置信号处理程序?我找不到关于
sigact()的任何信息
在快速搜索之后。@Andrew是的,我修复了输入错误使用
sigaction
而不是
signal
,您将能够保护您的处理程序不被您想要的任何其他信号打断。这不是我的代码,这是我认为错误的一个示例。好的。希望答案能够解释您的担忧是不必要的。我会ecommend
sigaction
如果该API对您可用,请阅读
sigaction
手册,该手册将提供更多详细信息。如果可以使用
sigprocmask()
etc,
sigaction()
也可以,而我可以想象使用
sigaction()
和无
sigprocmask()
(从上世纪90年代早期的一个实现,也许),你不太可能找到<代码> SIGPROMASK()/<代码>,没有<代码> SIGATAON()/<代码>;所以我不太可能认为它是“不可能的”,并且不担心可能。