C 在多线程信号处理程序中调用fflush?

C 在多线程信号处理程序中调用fflush?,c,multithreading,fflush,C,Multithreading,Fflush,我有一个实现多线程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代理的基本草图:

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);
}

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

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


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

因此,我需要阻塞异步传递并创建一个专用线程,该线程通过以下方式同步接收信号:,调用
sigwait
?不,您只需要不从信号处理程序调用不异步安全的函数。这样做不安全。例如,您的信号处理程序可以设置一个您声明为
volatile sig_atomic_t
的标志,然后返回,如果您的一个线程检测到该标志已设置,则可以刷新流。或者,也可以使用信号以外的机制。您编写的内容仅适用于受互斥保护的流。后者自C11以来已标准化。在C11标准之前,代码可能不会死锁,但仍可能表现出其他一些奇怪的行为,例如刷新另一个线程的半满缓冲区。@alk:True,尽管POSIX要求标准IO函数在POSIX线程存在的时间内保持线程安全,因此,在问题所涉及的类UNIX平台上,流的互斥保护时间可能更长。