Reliably killing child processes in a crash

Started by
8 comments, last by Extrarius 15 years, 4 months ago
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
Advertisement
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.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

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.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
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.
Quote:Original post by spraff
Here's a question for the Guru's, will a modern OS ever terminate a process without sending it a signal first?
AFAIK Windows XP (no idea whether Vista changes this) can terminate your process without sending it any signal whatsoever.

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.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by spraff
Exceptions won't do it, not every crash raises an exception.[...]
Can you give any examples? I don't think TerminateProcess raises an exception, but that isn't a crash.

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.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Seg faults don't throw exceptions, you need signals.
Quote:Original post by spraff
Seg faults don't throw exceptions, you need signals.
The 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.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by swiftcoder
Quote:Original post by spraff
Seg faults don't throw exceptions, you need signals.
The 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.
I 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).
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk

This topic is closed to new replies.

Advertisement