1

I frequently run programs that run for several days, testing successive integers for various criteria. I like to know where a program is up to, so I usually have it print out a message every, say, 100000000 trials, but it would be nice if I could get intermediate results by sending the program a signal. The kind of thing I have in mind is something like this:

Create signal handler to print out value of n and resume in loop

Register signal handler
n=1
while( 1 ) {
    If n fits some criterion, print n
    n++
}

with the idea that I could then use kill -SIGTYPE processid to get the intermediate results. Is it possible to do what I want? And if so, how? The examples I have seen that use signal handling in C all seem to exit immediately after having dealt with the signal, rather than resuming from the point where the signal was caught.

CrimsonDark
  • 661
  • 9
  • 20
  • "*exit immediately after having dealt with the signal*" depends on your usage of e.g. `sigaction()` ... sure it's possible to do what you want. Just don't print from inside the signal handler, use a flag (`volatile sig_atomic_t`) instead. –  Jan 15 '18 at 11:25
  • 3
    I bet you have missed this [one](https://stackoverflow.com/questions/17766550/ctrl-c-interrupt-event-handling-in-linux). – Gaurav Pathak Jan 15 '18 at 11:26
  • On which operating system? Pure standard C11 defines quite poorly what signals are and can do. – Basile Starynkevitch Jan 15 '18 at 11:38
  • Wht kind of programs are you writing? Please **edit your question** to improve it (motivate it, give more details). – Basile Starynkevitch Jan 15 '18 at 11:55
  • Without additional details: what OS you are coding on? what kind of application? ... your question is unclear. – Basile Starynkevitch Jan 15 '18 at 12:05
  • Possible duplicate of [Ctrl + C interrupt event handling in Linux](https://stackoverflow.com/questions/17766550/ctrl-c-interrupt-event-handling-in-linux) – Eldelshell Jan 15 '18 at 18:40

1 Answers1

3

No (in principle), you should not call printf or fputs (etc...) from a signal handler, and on Linux this restriction is documented, see signal(7) and signal-safety(7). Take time to understand the notion of async-signal safe functions (the only ones you can call from inside a signal handler -even indirectly- without undefined behavior).

(I guess you are on Linux, or at least on some POSIX or Unix-like system)

However, there is a usual way to overcome that: set some volatile sig_atomic_t flag in your signal handler, and test that flag regularly in your program main loop.

Another possibility could be to set-up (using pipe(2)), at initialization, a pipe(7) to self, and have a signal handler which write(2)-s one or a few bytes into that pipe (notice that write(2) is async-signal-safe, but fprintf or malloc are not). Your event loop would check (using poll(2)) that pipe for readability and read(2) it when possible. This common trick is often documented, e.g. in Qt.

Notice that signal handling is practically OS specific (e.g. different on Linux and on Windows), and has some common behaviour in various POSIX / Unix systems.

For programs running several days, you probably want them to also handle SIGTERM. You might then save some persistent state (e.g. in some database, in a file, perhaps using sqlite or gdbm) and be able to restart from such a saved state. Read about application checkpointing. You probably should think of saving (and be able to restart from) the state of your program early in its design. Perhaps you'll use time(7) facilities to save e.g. every hour the state of your program (look into setitimer(2), alarm(2), SIGALRM etc...).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Many thanks to all who replied. The comment from @Guarav was particularly helpful as was the answer that I have marked as correct. – CrimsonDark Jan 16 '18 at 05:04