On June 8, 2016 3:05:37 AM EDT, Klemens Morgenstern
Am 08.06.2016 um 04:06 schrieb Rob Stewart:
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.
I see your point. You could provide a default timeout for that case and include a function permitting the user to override that default.
Sry, but no. I don't see the point of timeouts, especially default ones. In this case it is quite clear, that there's no point in continuing, so why put in timeout?
Your approach gives the child no chance to shut down gracefully. It cannot close database connections, remove temporary files, clean up content in shared memory, whatever.
Sending signals on posix systems may not terminate a process either. That's why you fall back on SIGKILL. On Windows, you try the WM_CLOSE approach and fall back on TerminateProcess().
Difference is: every posix program can catch SIGTERM, not every windows program will get WM_CLOSE - console applications will never receive that. It depends on the compile options.
Some console apps can be written to process such messages, but most won't, of course. What's more, if an app doesn't handle the message, you're no worse off than when you just call TerminateProcess().
Now for this to be part of the process core library (i.e. included in boost/process.hpp) it would need to work like this both platforms:
//father child c(...); c.request_exit();
//child this_process::on_exit_request(std::function
func); That's not possible, so it won't be in the library. It might be added to the platform-extensions though, i.e. you could have something like the following functions if you include boost/process/posix.hpp or boost/process/windows.hpp (needs to be distinguished by #ifdef)
posix::send_terminate(child &); windows::send_wm_close(child&); windows::send_console_kill(child&);
I have no problem having a platform-specific function there, but if I have a function in the multi-platform part of boost.process it has to behave the same everywhere.
I see that you only want to send the nice termination signal if the child can install a handler in a common way. I was missing that side of the equation. The Windows issue is whether it's possible to determine, at compile time or runtime, whether an association has a GUI message loop or not. If so, you'd have to install a message loop handler for WM_CLOSE, and if not, you'd have to use SetConsoleCtrlHandler() to install a callback. I don't know much about Windows message handler loops, but you could install a message hook if there isn't a better way to integrate into the app's own message loop.
Joël Lamotte recommended a similar solution and will send me some examples, so a child::request_exit() function might be added.
The remote thread technique sounds interesting.
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));
Why not c.terminate(milliseconds(100)) and c.kill()?
Yeah would be possible, too. Though as written above, there won't be a terminate-request member-function of child. But what you could do is this.
some_magic_terminate_request(c); //your SIGTERM impl.
if (!c.wait_for(milliseconds(100)) c.terminate();
I'm confused why you think some_magic_terminate_request() should be a free function, while terminate() is a member function. ___ Rob (Sent from my portable computation engine)