Linux:pthread_cond_signal() 在 Signal Handler() 中不起作用

Posted

技术标签:

【中文标题】Linux:pthread_cond_signal() 在 Signal Handler() 中不起作用【英文标题】:Linux : pthread_cond_signal() is not working inside a Signal Handler() 【发布时间】:2015-06-17 11:39:33 【问题描述】:
Summary
-----------
1. In main() am going for pthread_cond_wait().
2. In signal handler() am waking main() using pthread_cond_signal().
3. But main() is not coming out from pthread_cond_wait().

这里有什么问题?帮帮我。

#include <stdio.h>  
myclass *myObj = NULL;

我主要是在等待一个信号:

int main()

    myObj = new myclass;    
    /* do something */
    myobj->gotoWait(); <=== Wait blocked for ever.
    /* do clean up here */
    return 0;

向主线程发送信号的信号处理程序:

static void signalHandler(int sig, siginfo_t *siginfo, void *context)

    myObj->wakeFromWait();

实现信号等待和发送的实际类。

这里有什么问题?

myclass::gotoWait()

    pthread_mutex_lock(&mtx);
    pthread_cond_wait(&cnd, &mtx);
    pthread_mutex_unlock(&mtx);
 
myclass::wakeFromWait()

    pthread_mutex_lock(&mtx);
    pthread_cond_signal(&cnd, &mtx);
    pthread_mutex_unlock(&mtx);

【问题讨论】:

这里有什么问题? ①你没有给我们MCVE。 ② 您正在使用没有谓词的条件变量,即使没有虚假唤醒,这对于任何重要的应用程序都可能是不正确的。 ③ 你等待一个条件变量而不期待spurious wakeups。 ④ 你错误地调用了pthread_cond_wait——这是怎么编译的? ⑤ 你在信号处理器中做了不安全的事情。 【参考方案1】:

在信号处理程序中,只允许非常有限数量的系统调用。

见 man 7 信号

http://man7.org/linux/man-pages/man7/signal.7.html

为了安全起见,我的建议是,所谓的“自管技巧”。 http://man7.org/tlpi/code/online/diff/altio/self_pipe.c.html

您可以启动一个线程,在 self 管道上运行一个选择循环并调用您的适当处理程序。

您的代码有什么问题?您在 Signal 处理程序中锁定了一个互斥锁

编辑:这里有信号指南 http://beej.us/guide/bgipc/output/html/multipage/signals.html

【讨论】:

感谢@schorsch_76 提供有关自我管道的有效信息和输入。【参考方案2】:

也许您可以使用 sigprocmask() 来确保给定信号不会到达代码中的特定点,然后信号处理程序无法在该点执行。 例如:* 下面的代码来自 James Sullivan's article

锁定/解锁(可能)即将到达信号的功能:

void signal_lock (sigset_t *save) 
    sigset_t set;

    sigfillset(&set); /* fill `set` with __all__ signals */
    sigprocmask(SIG_BLOCK, &set, save); /* no more signals :-)  */


void signal_unlock (sigset_t *save) 
    sigprocmask(SIG_SETMASK, save, NULL); /* enable again */

在致电signal_lock()之后...

sigset_t tmp;

signal_lock(&tmp); /* we locked all signals --
                    * no signal will arrives until signal_unlock() */
pthread_mutex_lock(<pthread_mutex_t*>);
/* do your stuff */
pthread_mutex_unlock(<pthread_mutex_t*>);
signal_unlock(&tmp); /* unlock signals --
                      * only signals allowed before signal_lock()
                      * may arrive */

我建议您仔细阅读 James Sullivan 撰写的 amazing article,它可以更好地解释事情:-)

【讨论】:

以上是关于Linux:pthread_cond_signal() 在 Signal Handler() 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 pthread_cond_signal 的优雅线程终止证明有问题

如果 pthread_cond_signal 是线程中的最后一次调用,是不是存在数据竞争?

Linux中 条件变量为啥要用互斥锁来保护?

pthread_cond_wait 丢失来自 pthread_cond_signal 的信号

条件变脸pthread_cond_signal丢失问题

perfreduce pthread_cond_signal via wait counter