Reliably killing child processes in a crash
Hi everyone.
When my application crashes, any threads it created will be destroyed, but if I have created processes they will continue to live independently, right?
I know how to capture SIGINT etc and can kill my spawn there, but that doesn't cover all cases (after a SIGSEGV for example, program behaviour is formally undefined, AFAIK).
Is there a general-purpose reliable method for cleaning up child processes? Cross-platform solutions would be nice :)
Thanks
One way to accomplish this is with a keep-alive message. Basically, once every 10 seconds the parent process sends each of its children a message, to let them know it is still alive, and if no message is received for 20 seconds, each child process terminates itself.
Quote:Original post by spraff
When my application crashes, any threads it created will be destroyed, but if I have created processes they will continue to live independently, right?
I know how to capture SIGINT etc and can kill my spawn there, but that doesn't cover all cases (after a SIGSEGV for example, program behaviour is formally undefined, AFAIK).
You have two competing standards, here, I believe. I can't be sure right now because my copy of the C++ standard is at work.
But POSIX says:
Quote:
The behavior of a process is undefined after it ignores a SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal that was not generated by kill(), sigqueue(), or raise().
I take this to mean that you may install a handler for SIGSEGV.
But in any handler you may only call async-signal-safe functions (a bit further down on that last link). Fortunately kill() is such a function.
It is only after the handler has returned that the behaviour is undefined (according to POSIX).
Quote:Is there a general-purpose reliable method for cleaning up child processes? Cross-platform solutions would be nice :)
AFAIK, Windows has no formal notion of "child processes", so unless there's a canned wrapper available, things will be somewhat different. I'm intrigued by other peoples' responses to this because I'll be porting a library to Windows soon that is designed to spawn and communicate with auxiliary processes.
EDIT: perhaps use _set_se_translator on Windows?
If you want a last-resort exception handler in windows, you can install one using "SetUnhandledExceptionFilter". If you want a first-resort exception handler in windows (that will also catch C++ exceptions, so you need to filter based on exception type), you can install one using "AddVectoredExceptionHandler". In MSVC, you can also use the __try / __except keywords to install scoped exception handlers.
You can find most* child processes using "CreateToolhelp32Snapshot" and "Process32First" / "Process32Next" to iterate over all processes and form a relationship tree based on process IDs (using GetCurrentProcessID to find the parent ID to use as a root), then use "OpenProcess" to turn the ID into a handle and then "TerminateProcess" to kill it.
* Most but not all because windows does not keep information about a process after it's handles are closed, so if you have process A create process B, then process B create process C, then process B closes, there won't be an easy way to identify that process C was indirectly spawned by process A.
You can find most* child processes using "CreateToolhelp32Snapshot" and "Process32First" / "Process32Next" to iterate over all processes and form a relationship tree based on process IDs (using GetCurrentProcessID to find the parent ID to use as a root), then use "OpenProcess" to turn the ID into a handle and then "TerminateProcess" to kill it.
* Most but not all because windows does not keep information about a process after it's handles are closed, so if you have process A create process B, then process B create process C, then process B closes, there won't be an easy way to identify that process C was indirectly spawned by process A.
Exceptions won't do it, not every crash raises an exception.
Here's a question for the Guru's, will a modern OS ever terminate a process without sending it a signal first?
A horribly hacky way to do it would be to wrap process creation in a function that synchronises this with some database (heck, the filesystem would do) and you could then have a simple (hence verifiable) process which monitored lost PIDs.
Keepalive messages seem a bit dirty to me. I was thinking the parent process could hold the STDIN file handle to the child, and crashing would mean that file handle gets closed. The child could detect this although I want to allow third-party plug-ins which might use STDIN differently.
Here's a question for the Guru's, will a modern OS ever terminate a process without sending it a signal first?
A horribly hacky way to do it would be to wrap process creation in a function that synchronises this with some database (heck, the filesystem would do) and you could then have a simple (hence verifiable) process which monitored lost PIDs.
Keepalive messages seem a bit dirty to me. I was thinking the parent process could hold the STDIN file handle to the child, and crashing would mean that file handle gets closed. The child could detect this although I want to allow third-party plug-ins which might use STDIN differently.
Quote:Original post by spraffAFAIK Windows XP (no idea whether Vista changes this) can terminate your process without sending it any signal whatsoever.
Here's a question for the Guru's, will a modern OS ever terminate a process without sending it a signal first?
Quote:Keepalive messages seem a bit dirty to me. I was thinking the parent process could hold the STDIN file handle to the child, and crashing would mean that file handle gets closed. The child could detect this although I want to allow third-party plug-ins which might use STDIN differently.That approach works, but again, only on *nix, where you have signals anyway - so a bit redundant.
Quote:Original post by spraffCan you give any examples? I don't think TerminateProcess raises an exception, but that isn't a crash.
Exceptions won't do it, not every crash raises an exception.[...]
The best alternative I can think of is a 'launcher' process that creates the base process and regularly iterates through all processes to find children. Once it detects that the base process isn't running, it can close all children.
Quote:Original post by spraffThe same point of confusion keeps coming up here: Extarius is talking about Windows, while you are talking about unix. You asked for a portable solution, and portable implies Windows as well.
Seg faults don't throw exceptions, you need signals.
Quote:Original post by swiftcoderI believed that to be the problem, which is why I asked for clarification. Segmentation faults are known as "access violations" on windows, and do indeed throw an exception (though not the C++ kind).Quote:Original post by spraffThe same point of confusion keeps coming up here: Extarius is talking about Windows, while you are talking about unix. You asked for a portable solution, and portable implies Windows as well.
Seg faults don't throw exceptions, you need signals.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement