c - 有没有办法在拥有带有信号处理程序的多线程程序的同时确保原子性



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

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

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

另外,如果我不说我会重构你的代码,那将是我的失职。在信号处理程序中可以做的事情数量是有限的(例如,没有malloc,没有printf等)。

将一个线程专用于信号处理并让它执行sigsetjmp,信号处理程序会siglongjmp

或者让信号处理程序设置一个易失性的全局(例如 signal_occurred ),在基础级别进行监视。

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

你需要两个锁。 一个用于func() ,一个用于保护进程的信号掩模。

您还必须使信号的屏蔽和取消屏蔽原子:

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

由于pthread_sigmask()周围没有锁,线程可能会在执行重叠时破坏进程 sigmask。

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

相关内容

  • 没有找到相关文章

最新更新