I am vaguely following this thread as I don't have lots of time but am
interested in the process library.
I have also written a C++ process (and signals) library supporting
windows/OSX/Linux/Android (for an employer though so I can't propose it for
boost). It actually suprised me how many platform differences existed that
needed to be worked around in writing this library compared to others I
have written.
I also did something similar to Klemens if what I undertood is correct, I
did a fallback scenario of send TERM if not closed within time period send
a KILL. I didn't really like it though and wonder if the std::thread
destructor behavior is better to std::terminate if the child is still
running but not detached and treat it more like a bug to destroy an active
process instance than something to rely on to close it.
Not having a SIGTERM equivilant for windows processes bothered me as
SIGKILL is just too nasty as a default as mentioned. So I looked into this
quite thoroughly. For GUI processes you can easily send WM_CLOSE message to
it to simulate something akin to a SIGTERM. I think I used a WM_CLOSE from
memory. I know there was a choice between QUIT and CLOSE, I think CLOSE was
more suitable but I cant recall the exact reason now and may be wrong.
For console processes I only found bad options. I found something that
worked quite well but ended up dropping it in the end as it was not
required and was super hacky IMO. I only ever wanted to SIGTERM my own
processes in the end so just used a non generic solution of a named pipe to
listen for signals and raise() to local process.
The GenerateConsoleCtrlEvent() comes close to doing what we want but its
got the worst behaviour in how to choose who gets the signal delivered and
is not sufficient (even when creating processes to detach/attach to other
consoles to generate the events). In the end I followed the basic idea
proposed at:
http://www.latenighthacking.com/projects/2003/sendSignal/
With extra ideas proposed in comment (20110401) and a few extra changes of
my own. I got this working well in all scenarios I could think of to test
on win32 and 64 up to Win7 (I think I went down to XP but cant recall for
sure).
The idea is basically to use the mechanism that GenerateConsoleCtrlEvent()
uses to deliver the signal, but you choose the process where to deliver it
yourself instead of using the stupid rules that GenerateConsoleCtrlEvent()
follows.
The idea is to create a new "helper" process, have it register a signal
handler, raise a signal to itself and in the handler walk back the stack to
find the entry point where the signal was generated. It turns out that the
function where the signal was generated (I think it was
kernel32!CtrlRoutine) this function has the correct prototype for
CeateRemoteThread and is in the kernel32.dll so is in the same location in
all processes on the system and is how GenerateConsoleCtrlEvent() is
implemented.
So you basically then find the process you care about, create a remote
thread in it to call the specified function and presto you end up with a
SIGTERM that can be handled by a normal signal() handler in a console
process.
I hope my research was useful, but this approach was not really acceptable
to me and I dont think would be to the boost community. Maybe another idea
might arise from it though, in which case I would love to hear about it.
On 7 June 2016 at 18:59, Klemens Morgenstern
Am 07.06.2016 um 10:37 schrieb Rob Stewart:
On June 6, 2016 6:49:44 AM EDT, "Klaim - Joël Lamotte"
wrote: On 6 June 2016 at 12:00, Klemens Morgenstern
wrote: 2. The way child process termination is implemented for each platform
should be documented.
Makes sense. It's TerminateProcess on windows and "kill -9" on posix. (also added)
That's too harsh as a default. Default signal handling in Posix systems means that sending SIGTERM first would signal a graceful exit. That doesn't mean the process will exit successfully or that it won't ignore the signal, so after waiting for a limited time (user specified with a default), you would send SIGKILL.
(You could actually send SIGTERM, SIGINT, and SIGQUIT, one after the other to increase the chance that the process recognizes the need to exit.)
On Windows, you can send WM_CLOSE. The process may respond within the allotted time and it may not (it certainly won't if it's an ordinary console app). TerminateProcess() is the final step if the process handle isn't signaled within the timeout period.
Thus, terminating a process behaves similarly on both platforms: try a nice signal, wait, then terminate it forcefully if need be.
I actually thought the same thing, but it is an issue of security. Consider this:
ipstream is;
child c("prog", std_in < is); is << generate_input() << endl;
Not if generate_input throws, I need to terminate the child, elsewise I get a deadlock (since "prog" waits for input). If you do not want this, you can detach it or join it. In that it is similar to std::thread, though it doesn't terminate the current process. Now using a timeout would be possible, but I really don't like to set an arbitrary value here.
Regarding the WM_CLOSE version: I currently don't think that is a really portable solution, since you signal the HWND not the Process, which means that console programs will cause problems here. Joël Lamotte recommended a similar solution and will send me some examples, so a child::request_exit() function might be added. Now if that happens, I still will not change the behaviour in child, but you might be able to do this then:
soft_exit se (child("thingy"), milliseconds(100));
It really depends on how this can be achieved on windows; I didn't look into that, because it's not part of the Process handling in the WinAPI, but maybe there's a workaround.
___
Rob
(Sent from my portable computation engine)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost