Thread: popen: safe to call in signal handler?

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445

    popen: safe to call in signal handler?

    if I use signal() or sigaction() to install a signal handler for SIGSEGV or other signals, is it safe to call popen() from inside the handler? it returns a FILE* so I'm guessing that it's a library function that calls pipe(), fdopen(), fork(), dup(), and exec*() on the back end, which are all legal calls inside a signal handler, so I'm guessing that it's ok. I am spawning the external program addr2line on a series of addresses obtained by calling backtrace(), and it appears to work fine, but I just want to make sure I'm not treading on undefined behavior territory.

  2. #2

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    printf isn't on the list either, but every example that I see uses it. if you assume that the list is a hard-and-fast rule, then you also cannot call any user code from inside a signal handler, and that seems pretty unreasonable. wouldn't you agree? after looking at the source for a couple of implementations of popen, including glibc's implementation, I've confirmed that it is in fact typically calling pipe, (v)fork, dup/dup2, and exec*, which are all approved functions, guaranteed by POSIX to work correctly. would you say that if it's not explicitly on the list, that I can't use it? that seems like an unnecessarily strict interpretation to me.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > would you say that if it's not explicitly on the list, that I can't use it?
    Except you have no control over the implementation of popen(), so you can't be sure that it will be fine in future.

    There's nothing to stop you using the POSIX API that is allowed to write a "popen" like function that does what you want.

    If you want to write to a file in a signal handler, then it's a lot safer to use descriptors and write().
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    The rule seems to be that it can't do any dynamic memory allocation/deallocation or use static/global data structures, since if it was interrupted the data structures could become inconsistent. One point here is that you're supposed to save/restore errno!

    In the examples I've seen of signal handlers that call printf, they are just printing a string with nothing in the variable parameter list. That's probably what makes it safe since there would presumably be nothing extra behind-the-scenes in that scenario.

    popen is apparently not guaranteed to make no use of such things.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    if I were to fork first, and then do what I need to do, and call exit() without returning, would that be a safe solution to this problem?

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    When the application calls fork() from a signal handler and any of the fork handlers registered by pthread_atfork() calls a function that is not async-signal-safe, the behavior is undefined.
    There's that risk.

    Why not just let the default handler generate a core dump, then post-process the dump? Or fix the bugs

    gg

  8. #8
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by Codeplug View Post
    There's that risk.
    no risk in this case, as this program is single-threaded.

    Why not just let the default handler generate a core dump, then post-process the dump?
    it needs to happen in real time so that it can notify me by email that something went wrong.

    Or fix the bugs
    that's why I'm generating a stack trace in the first place, to find the point at which the crash is happening, so that I can fix the bugs. this is a pretty large system (100k+ lines), going back more than 4 years, and some of the older code is lower quality, but in the absence of compiler warnings, it's difficult to proactively find bugs. I simply have to wait for the magic combination of circumstances that will make the program crash, and react to it after the fact.

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You'll have everything you need to debug the crash with a core dump. Why limit yourself to a manual stack trace?

    >> it needs to happen in real time
    So either monitor for the creation of a core dump, or signal something that a core dump is about to occur using this trick: How to handle SIGSEGV, but also generate a core dump - Alex on Linux
    But don't call printf like in the example since that's not in the list.

    gg

  10. #10
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by Codeplug View Post
    I tried that, but even after setting ulimit -c unlimited, it still doesn't create core dumps. not sure where to go from there.

  11. #11

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. signal handler does not print
    By barramundi9 in forum C Programming
    Replies: 4
    Last Post: 07-27-2011, 11:20 PM
  2. popen thread safe?
    By Drogin in forum Linux Programming
    Replies: 3
    Last Post: 04-01-2011, 07:36 AM
  3. Signal handler for assert()
    By jeffcobb in forum Linux Programming
    Replies: 17
    Last Post: 06-10-2010, 08:36 PM
  4. Alarm signal around popen
    By rotis23 in forum C Programming
    Replies: 3
    Last Post: 03-10-2003, 08:51 AM
  5. signal handler
    By falconetti in forum C Programming
    Replies: 1
    Last Post: 02-21-2002, 07:54 PM