Is there a way to ensure atomicity while having a multithreaded program with signal handlers?

前端 未结 3 1485
离开以前
离开以前 2021-01-23 16:10

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 pro         


        
相关标签:
3条回答
  • 2021-01-23 16:22

    You may use the test mutex functions (trylock) in this kind of undefined situations, to be safe. And with this, you don't necessarily need to block too.

    0 讨论(0)
  • 2021-01-23 16:23

    You want pthread_sigmask, the multithread version of sigprocmask

    Here's some sample pseudo code:

    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 ...
    }
    

    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.

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

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

    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.

    0 讨论(0)
  • 2021-01-23 16:42

    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.

    0 讨论(0)
提交回复
热议问题