3

我有一个实现多线程 Web 代理的基本草图:

FILE *proxy_log_file;

static void
SIGUSR1_handler(int sig)
{
    (void)sig;
    fflush(proxy_log_file);
}

int
main(int argc, char **argv)
{
    proxy_log_file = fopen("proxy.log", "a");
    Signal(SIGUSR1, SIGUSR1_handler);
}

这个想法是网络管理员可以通过使用命令向Web 代理kill发送信号来将缓冲的日志条目刷新到日志文件。SIGUSR1但是,我不确定fflush在信号处理程序内部调用是否是个好主意。我知道fflush是线程安全的,但不认为它是异步信号安全的。fflush在多线程的信号处理程序内部调用可能会出现什么并发问题?

4

1 回答 1

3

假设您的线程调用一个标准 IO 函数,该函数锁定了一个保护流数据结构的互斥体。在解锁该互斥体之前,会传递一个信号,并调用您的信号处理程序。您的信号处理程序调用fflush()并尝试锁定互斥锁。您的线程和您的标准 IO 流现在将永远死锁,因为您的信号处理程序将在互斥体上等待,但它永远不会变得可用,因为您的线程将阻塞,直到信号处理程序返回。这是一个经典的僵局。

这就是线程和信号处理程序之间的区别。如果一个线程试图锁定一个互斥体并且发现它已经被锁定,它就会进入睡眠状态,其他线程将运行,并且迟早持有互斥体的线程将解锁它。但是您的信号处理程序不是线程,因此它不会进入睡眠状态并让被中断的线程运行 - 该线程将简单地阻塞,直到信号处理程序返回,在上面的示例中,它永远不会。

于 2016-04-30T19:22:00.427 回答