3
votes

I have a 'C' application in linux where in i have register SIGALRM handler. My SIGALRM handler updates some global data that other threads are also accessing. Requirement: In order to protect the global data, i need to block the signal completely while i am accessing it inside the thread. So i need a way to implement it. Problem: I am not able to block the signals completely. sigprocmask is not working. Although it blocks signal if main is the only thread running. But when multiple threads are running SIGALRM keeps on coming. I have tested pthread_sigmask but that updates the signal mask for current thread only.

Adding code logic:

sig_atomic_t atm_var;
void signal_handler()
{ 
    atm_var++; 
}

void thread_func()
{
    pthread_sigmask(UNBLOCK,...);
    while(1)
    { 
        /* some stuff */
        pthread_sigmask(BLOCK,...);
        /* critical section, can easily access or modify atm_var */
        pthread_sigmask(UNBLOCK,...);
    }
}

int main()
{
    sigprocmask(BLOCK,...);
    pthread_create(...,thread_func,...);

    sigaction(SIGALRM,...);
    setitimer(ITIMER_REAL,...);

    while(1)
    {
    }
}

Adding one more point: How safe it is to modify a sig_atomic_t variable (that signal handler is modifying) in main or other threads?

OR

Will it be safe practice to not to block signal while i modify the sig_atomic_t variable inside main or other threads?

1
can you post code here.will be easy to point out - user2760375
Use timer_create instead of setitimer. It allows you to specify a thread to deliver the signal to. - PSkocik

1 Answers

4
votes

Your problem is that various signals can be directed at the whole process or a particular thread. When directed at the whole process then they will be delivered to any thread that doesn't have them blocked.

man (7) signal

A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.

Because the signal masks are inherited by each thread from whatever thread created them, a fairly standard technique is to block them in the creator (for simplicity let's say that is main) and then let each spawned thread unblock signals as appropriate.

A common variation on this is to block them in main, and keep them blocked in all spawned threads except one. That one thread unblocks the signals and all process directed signals get aimed at it to handle.

The above is probably what you want to do. You probably are properly blocking SIGALRM in the thread which is running the signal handler. Unfortunately that isn't going to prevent SIGALRM from being delivered to a second thread.