本文介绍了有一个具有信号处理程序的多线程程序时,有没有办法确保原子性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有这样的程序(使用伪代码):

If I have a program like this (in pseudocode):

mutex_lock;
func() {
    lock(mutex_lock);
    // Some code (long enough to make a
    // race condition if no proper synchronisation
    // is available). We also going to call a signal,
    // say, SIGINT, through (ctrl-c), while we are in
    // the range of locking and unlocking the lock.
    unlock(mutex_lock);
}

sig_handler_func(sig) {
    // Say, we are handling SIGINT (ctrl-c) signal
    // And we need to call func from here too.
    if (sig == SIGINT) {
        func();
    }
}

main() {
    // Calling func from main
    func();
}

然后,当试图从func中获取锁时,将会出现一个死锁,而该锁已经从主"调用者那里获取了.我想知道是否有一种方法可以挂起C语言的信号处理,特别是在本例中何时进入func并获取锁,然后恢复信号处理并在退出func时调用处理程序.

then there would be a deadlock when trying to acquire the lock in func, while it is already acquired from the 'main' caller. I was wondering if there is a way to suspend the signal handling in the C language, specifically, when, in this example, entering func and acquiring the lock, and resume the signal handling AND call the handlers upon exiting func.

推荐答案

您需要pthread_sigmask,它是sigprocmask

这是一些示例伪代码:

int
main(void)
{
    sigset_t omask;
    sigset_t nmask;

    // add as many signals as you want to the mask ...
    sigemptyset(&nmask);
    sigaddset(&nmask,SIGINT);

    // [temporarily] block signals
    pthread_sigmask(SIG_BLOCK,&nmask,&omask);

    // call function safely
    func();

    // restore signal mask
    pthread_sigmask(SIG_SETMASK,&omask,NULL);

    // pending signals should occur now ...
}

我不太确定,但是,您可能需要使用pthread_sigmask来阻塞除一个线程之外的所有线程的信号,并仅从该线程执行上述操作.

I'm not totally sure, but, you may need to use pthread_sigmask to block signals in all but one thread and do the above from that thread only.

此外,如果我不说我将重构您的代码,那我也会被解雇. [除此以外]您在信号处理程序中可以做的事情是有限的(例如,没有malloc,没有printf等)

Also, I'd be remiss if I didn't say that I'd refactor your code. The number of things you can do in a signal handler [aside from this] is limited (e.g. no malloc, no printf, etc.)

指定一个线程进行信号处理,并使其执行sigsetjmp,信号处理程序执行siglongjmp.

Dedicating one thread for signal handling and having it do sigsetjmp and the signal handler does siglongjmp.

或者让信号处理程序设置一个易失的全局变量(例如signal_occurred),该变量在基本级别上受到监控.

Or have the signal handler set a volatile global (e.g. signal_occurred) that is monitored at base level.

因此,您在信号处理程序中要做的所有繁重工作"都可以在基本任务级别上完成,在此您可以执行任何操作.

Thus, all the "heavy lifting" that you'd be doing in the signal handler can be done from base task level where you can do anything.

这篇关于有一个具有信号处理程序的多线程程序时,有没有办法确保原子性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 16:16