在使用带有信号处理程序的多线程程序时,有没有办法确保原子性?

时间:2016-07-11 18:38:40

标签: c signals posix mutex atomicity

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

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时调用处理程序。

3 个答案:

答案 0 :(得分:2)

您需要pthread_sigmasksigprocmask

的多线程版本

这里有一些示例伪代码:

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来阻止除一个线程以外的所有线程中的信号,并且仅从该线程执行上述操作。

另外,如果我没有说我重构你的代码,我会失职。您可以在信号处理程序[除此之外]执行的操作数量有限(例如,无malloc,无printf等。)

专用一个线程进行信号处理并使其执行sigsetjmp,信号处理程序执行siglongjmp

或者让信号处理程序设置一个在基级监控的易失全局(例如signal_occurred)。

因此,所有"重举"您在信号处理程序中所做的事情可以从您可以执行任何操作的基本任务级别完成。

答案 1 :(得分:2)

You need two locks. The one used inside your func(), and one to protect the process's signal mask.

You have to make masking and unmasking the signal atomic also:

static  pthread_mutex_t mask_mutex = PTHREAD_MUTEX_INITIALIZER;
sigset_t old_set;
sigset_t new_set;

sigemptyset( &new_set );
sigaddset( &new_set, SIGINT );

pthread_mutex_lock( &mask_mutex );

pthread_sigmask( SIG_BLOCK, &new_mask, &old_mask );

func();

pthread_sigmask( SIG_SETMASK, &old_mask, NULL );

pthread_mutex_unlock( &mask_mutex );

With no lock around the pthread_sigmask(), threads are likely to corrupt the process sigmask as execution overlaps.

答案 2 :(得分:-1)

为了安全起见,您可以在这种未定义的情况下使用 test mutex 函数(trylock)。有了这个,你也不一定需要阻止。