Am 08.06.2016 um 10:33 schrieb Rob Stewart:
On June 8, 2016 3:05:37 AM EDT, Klemens Morgenstern
wrote: 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.
A timeout doesn't make sense if you have no standard way to signal the child to exit. If you implement your version of that, you can use chlid::wait_for and then terminate. The child class is meant to be joined before destructing; the terminate on destruction is for exceptions.
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.
That, AND it ought to be the default on the system for exit requests.
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.
It doesn't work really, especially since SetConsoleCtrlHandler does only allow two values (Ctrl+C & Ctrl+Break), which are both not clearly termination requests, but more of a terminate command I think. Also to do that, I would need to put all those child processes on a new process group, which would mean, that Ctrl+C will NOT be transmitted to them. That's also a dealbreaker.
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.
Because I would be fine to have it as an extension in the posix- or windows-namespace, but not in the core-library. Hence it won't be a method of child.
___ Rob
(Sent from my portable computation engine)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost