From 41f958c4cf68541a48b20ceb608afe2308a6e6a7 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 17 Aug 2018 23:14:37 +0300 Subject: Add timed_wait() and kill() to process class, change try_wait() signature Review Backup --- libbutl/process.cxx | 69 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 9 deletions(-) (limited to 'libbutl/process.cxx') diff --git a/libbutl/process.cxx b/libbutl/process.cxx index 384af29..c0914b4 100644 --- a/libbutl/process.cxx +++ b/libbutl/process.cxx @@ -9,7 +9,7 @@ #include #ifndef _WIN32 -# include // SIG* +# include // SIG*, kill() # include // execvp, fork, dup2, pipe, chdir, *_FILENO, getpid # include // waitpid # include // _stat @@ -46,6 +46,7 @@ #ifndef __cpp_lib_modules #include #include +#include #include #include #include @@ -55,10 +56,11 @@ #include // move() #include -#ifdef _WIN32 +#ifndef _WIN32 +#include // this_thread::sleep_for() +#else #include #include // milli -#include #include // __argv[] #include // find() #endif @@ -87,6 +89,10 @@ import butl.vector_view; import butl.small_vector; #endif +#ifndef _WIN32 +import std.threading; +#endif + import butl.utility; // casecmp() import butl.fdstream; // fdnull() #else @@ -509,7 +515,7 @@ namespace butl return exit && exit->normal () && exit->code () == 0; } - bool process:: + optional process:: try_wait () { if (handle != 0) @@ -518,7 +524,7 @@ namespace butl int r (waitpid (handle, &es, WNOHANG)); if (r == 0) // Not exited yet. - return false; + return nullopt; handle = 0; // We have tried. @@ -528,7 +534,39 @@ namespace butl exit = process_exit (es, process_exit::as_status); } - return true; + return exit ? static_cast (*exit) : optional (); + } + + template <> + optional process:: + timed_wait (const chrono::milliseconds& tm) + { + using namespace chrono; + + // On POSIX this seems to be the best way for multi-threaded processes. + // + const milliseconds sd (10); + for (milliseconds d (tm); !try_wait (); d -= sd) + { + this_thread::sleep_for (d < sd ? d : sd); + + if (d < sd) + break; + } + + return try_wait (); + } + + void process:: + kill () + { + if (handle != 0) + { + if (::kill (handle, SIGKILL) == -1) + throw process_error (errno); + + wait (); + } } process::id_type process:: @@ -1665,14 +1703,14 @@ namespace butl return exit && exit->normal () && exit->code () == 0; } - bool process:: + optional process:: try_wait () { if (handle != 0) { DWORD r (WaitForSingleObject (handle, 0)); if (r == WAIT_TIMEOUT) - return false; + return nullopt; DWORD es; DWORD e (NO_ERROR); @@ -1689,7 +1727,20 @@ namespace butl exit->status = es; } - return true; + return exit ? static_cast (*exit) : optional (); + } + + template <> + optional process:: + timed_wait (const chrono::milliseconds&) + { + throw process_error (ENOTSUP); + } + + void process:: + kill () + { + throw process_error (ENOTSUP); } process::id_type process:: -- cgit v1.1