Open gromakovsky opened 6 years ago
If you need to send a specific signal, then I would recommend using the unix package directly. I'm not opposed to providing additional functions in System.Process
to send other signals. However, keep in mind that this will not help at all if your Haskell process is killed by an executable compiled against an older version of the process library, or a different program that decides to send SIGTERM. Therefore, if this is really important to you, I would say adding a signal handler for SIGTERM is the right thing to do.
More generally: there's no way you can depend on cleanup actions ever being run in this manner. An external process may elect to kill your process with SIGKILL, for instance, or the machine may just shut down. Generally speaking, cleanup actions are useful for maintaining invariants within a single process, like ensuring locks are releases or file descriptors freed. However, cleanup actions which will have evidence outside of the process cannot ever be relied upon to be run, regardless of SIGINT vs SIGTERM.
Thanks for the answer. It's not really important for me to run all cleanup actions during shutdown and I understand that the program may be killed with SIGKILL. However, in 99% cases one my application will kill another my application, so in these 99% cases I have full control and I was thinking that it's better to do cleanup actions in these 99% cases. For example, my application may create temporary files (e. g. using withSystemTempFile) and I want them to be deleted when the application is stopped. If those files are not deleted, it won't break any invariants, but they will take some space on disk and if it happens multiple time (with SIGTERM it may happen every time the application is closed), those files can consume significant amount of disk space. So I think my choice will be to add a signal handler for SIGTERM.
I'm not opposed to providing additional functions in System.Process to send other signals.
The main difficulty is to understand how to do gracefully stop a process on Windows. We will probably try to figure out how do it (there are some recommendations here) and will submit a PR if we succeed.
I've been looking into this as I seem to get orphaned processes when restarting with SIGTERM. I suspect Haskell only kills threads triggering process cleanups on SIGINT.
I find this issue to be very confusing, @gromakovsky could you clarify? Is this about:
process
package. How do I make sure that it doesn't leave children behind?process
package to run some child processes. How do I make sure that those child processes clean up after themselves when they're terminated?If it's about question 1, that doesn't seem to be an issue for the process
package, since it's about child processes, not about the process itself. (An answer could be: install a SIGTERM handler that kills the main thread with an asynchronous exception. And make sure all your code is async-exception safe, i.e., put lots of bracket
everywhere.)
For point 2, the answer would be to use withProcess
(or something like it) -- that guarantees that children will be terminated.
The only function to stop a process I found is
terminateProcess
. According to the documentation, on Unix systems it will send the SIGTERM signal. I did some research and concluded that apparently when a Haskell process receives SIGTERM signal, it will not throw an exception to the main thread, but will stop everything rudely, so that, for example, second action passed tobracket
will not be executed. That differs from SIGINT handling which causesUserInterrupt
to be thrown. I used this code to test it. But I want to kill a process gracefully, to allowbracket
to do all cleanup actions.So I am wondering: shouldn't
process
have a function which will do it? Alternatively I can useSystem.Posix.Signals
fromunix
to send SIGINT directly (and do something else on Windows). Or I can set a special handler for SIGTERM in my Haskell program which will behave akin to SIGINT. I would appreciate any recommendations.