3

Global variables are not updated in signal handlers unless of atomic types like sig_atomic_t. Given the following 2 conditions, can I safely edit global variables in signal handler?

  1. If I define only one signal handler
  2. If I use a sa_mask of struct sigaction to block all signals for the handler
  3. Application is single threaded

Adding more details: I got a small global linked list keeping some info of its child process in it. Once I catch SIGCHLD (in parent process), in my signal handler I want to delete that node from the linked list. Can I perform this action in signal handler with above conditions and using some sort of pthread_mutex_trylock()?

Jay
  • 43
  • 1
  • 7
  • With regards to other signals or task-preemption? – bash.d Aug 14 '13 at 12:52
  • Both. I beleive task preemption wont happen since there is only one signal handler and until this handler completes, normal flow will not resume. Please tell if any other task-preemption. – Jay Aug 14 '13 at 12:55
  • 1
    POSIX signals are not queued, so you cannot assume you'll reliably get a separate `SIGCHLD` for each child. (If two child processes exit at roughly the same time, then only one signal is generated.) This means that you should either reap *all* pending children in the signal handler, or better yet, just set a `sig_atomic_t` flag to your main thread, or raise a semaphore to a worker thread to do the actual reaping. – Nominal Animal Aug 15 '13 at 17:14

2 Answers2

0

Signal handlers have a problem accessing static data structures. From this, you can get corrupted data and such. If you try and call printf() within a signal handler, many times you will get strange output.

The same is for global variables unless you use atomic types.

Signal handler won't see global variable

Community
  • 1
  • 1
KrisSodroski
  • 2,796
  • 3
  • 24
  • 39
  • Yep. Just recollected that signals can be asynchronous and signal handlers can be invoked any time. May be when the process was in mid way of updating global variable in its normal flow. Updating in signal handlers or while normal flow resumes, it will cause corruption. – Jay Aug 14 '13 at 13:03
0

The type sig_atomic_t is DEFINITELY going to be updated. You can't rely on any other type to be updated outside of the context of the signal handler. It may be, and there is definitely no guarantee that it WON'T be updated. However, this comes down to handling of caches and multiple processors, asynchronous execution and other such things. If the compiler believes that a variable won't change, it may load it into a register and not ever reload it. That is not allowed for sig_atomic_t, so it "won't go wrong".

This is similar to "updating global variables in different threads", the update needs to be done under locks or using special atomic types. You can't use locks in signal handlers, because signal handlers could be called when there is some lock held!

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • My application is single threaded. signals can be asynchronous and signal handlers can be invoked any time. May be when the process was in mid way of updating global variable in its normal flow. Updating in signal handlers or while normal flow resumes, it will cause corruption Can I use pthread_mutex_trylock() and safely edit global variables? (rather using pthread_mutex_lock() to avoid deadlock if lock was acquired by process in its normal flow ) – Jay Aug 14 '13 at 13:15
  • You can't use any form of locking in a signal handler, since there is no telling where the code was when calling the signal handler - it may be half-way through setting some `mutex` (e.g. the `pthread_mutex` that you try to lock). Can you edit your question to explain a bit more about what you are actually trying to do, what the global variable represents, etc? – Mats Petersson Aug 14 '13 at 13:19