How to prevent a process opened with popen() in C++ from receiving SIGINT signal?

1.1k views Asked by At

I opened a process(GNUplot) from C++ with the popen() function. When I Ctrl+C to terminate the process, GNUplot also receives SIGINT signal. I want to prevent this from happening as it has an unfavorable effect on what I do. (I prefer to handle the signal with my own signal handler function). How do I do that?

I plot using the plot '-' command and iterate through all the values I want to plot. If the gnuplot receives SIGINT in the middle, it might stop plotting in the middle without completing the entire plot. I want it to complete the entire plot. This is the unfavorable effect I have.

2

There are 2 answers

2
Basile Starynkevitch On BEST ANSWER

popen(3) is running a new shell /bin/sh -c on the command string.

The trap builtin of the shell is handling signals; with an empty first argument it is ignoring it. So you could do

 FILE* f = popen("trap '' TERM INT; gnuplot", "w");

BTW, POSIX trap requires the signals to be named without SIG prefix.

But that won't work, since gnuplot itself is explicitly handling signals. There is no way to avoid that outside of gnuplot. But take advantage of the free software nature of gnuplot: download its source code, study it, and patch it to fit your bizarre needs. FWIW, SIGINT and signal appear in several places in the source code of gnuplot-5.0.5.

However, you should consider (instead of using popen) to call the low level system calls explicitly (fork, execve, pipe, dup2, waitpid, signal ...). Read Advanced Linux Programming for details.


I strongly suspect that your question is an XY problem. You don't explain what "unfavorable effect" you actually want to avoid, and I am guessing you might avoid it otherwise.

I plot using the plot '-' command and iterate through all the values I want to plot. If the gnuplot receives SIGINT in the middle, it might stop plotting in the middle without completing the entire plot. I want it to complete the entire plot.

Actually you might set up two or three pipes (one for input, one for output, perhaps one for stderr, as seen on gnuplot side) for gnuplot. You need to go the low level system calls (explicit calls to pipe(2), fork(2) etc etc...). Your program should then have some event loop (probably based upon poll(2)...). And you would send a print "DONE" command to gnuplot after every plot '-' (don't forget to initialize with the appropriate set print '-' or have another pipe for the stderr of gnuplot). Your event loop would then catch that DONE message to synchronize. Read also this.

0
Václav Zindulka On

I had similar problem as you. I'm using tc command with -batch parameter and I need to keep it alive until it exits after reaching limit and is closed. My problem was that I was running two asynchronous popen processes and after throwing an exception, second process was killed. A lot of memory dumps etc. After finding this problem and fixing it I can now handle SIGINT, SIGTERM, ctrl+c without tc proces knowing anything about it. No need for traps or anything similar.