1

We recently had a discussion at work about signal handlers in C (Unix enviornment).

Someone mentioned that

(f)printf() is certainly thread-safe but not signal-handler safe.

What does the above statement mean? What aspect of (f)printf() make it not signal-handler safe? Is it because it accesses the stdout and stdin which are global and hence the function is not re-entrant?

Or is there some other aspect which I am missing?

liv2hak
  • 14,472
  • 53
  • 157
  • 270
  • 2
    Who said it's thread safe? `printf` is certainly not specified as being thread safe or reentrant. Most implementations probably don't have much internal shared state (if any) which can make it seen as thread safe, but there's nothing stopping multiple threads to get their output mixed up. – Some programmer dude Sep 15 '14 at 08:40
  • 2
    @JoachimPileborg: It is thread-safe simply because it doesn't use any global or static-local variables. – barak manos Sep 15 '14 at 08:43
  • 1
    @barakmanos: That is implementation-defined, isn't it? Nothing in the standard (up to C99 at least) *forbids* `printf()` to use static-local variables, e.g. for numerical conversions... (That would be a *bad* implementation, but not a non-conforming one...) – DevSolar Sep 15 '14 at 09:12
  • 1
    I don't see anything in POSIX either, so common sense must be used here on the side of library writers. – Pavel Šimerda Sep 15 '14 at 09:43

2 Answers2

4

There is actually fairly little that is legal to do in a signal handler directly. Instead, one must usually set some flag or trigger to do the real work outside the signal handling context. While handling a signal, the only functions you can call are those which are "async signal safe," which is described in detail here: What constitutes asynchronous-safeness

Community
  • 1
  • 1
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
2

As mentioned in here: http://www.gnu.org/software/libc/manual/html_node/Nonreentrancy.html#Nonreentrancy

If a function uses and modifies an object that you supply, then it is potentially non-reentrant; two calls can interfere if they use the same object.

In your case that object is stdout. When a signal arrives in the middle of a (f)printf() and if you use (f)printf in handler, both data could be corrupted as they operate on the same stream, stdout. Reentrancy is the root cause in that case. Even if you use the stream in just signal handler, two signal handlers can interfere.

Cem Özer
  • 1,263
  • 11
  • 19