aboutsummaryrefslogtreecommitdiff
path: root/libbutl/process.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-08-17 23:14:37 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-08-20 17:37:44 +0300
commit41f958c4cf68541a48b20ceb608afe2308a6e6a7 (patch)
treec4e92865e98b7a3b911d355525e984151b44da22 /libbutl/process.cxx
parentc00321b94d6b952d59257b4a7373a1199e874d98 (diff)
Add timed_wait() and kill() to process class, change try_wait() signature
Review Backup
Diffstat (limited to 'libbutl/process.cxx')
-rw-r--r--libbutl/process.cxx69
1 files changed, 60 insertions, 9 deletions
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 <errno.h>
#ifndef _WIN32
-# include <signal.h> // SIG*
+# include <signal.h> // SIG*, kill()
# include <unistd.h> // execvp, fork, dup2, pipe, chdir, *_FILENO, getpid
# include <sys/wait.h> // waitpid
# include <sys/types.h> // _stat
@@ -46,6 +46,7 @@
#ifndef __cpp_lib_modules
#include <string>
#include <vector>
+#include <chrono>
#include <cstdint>
#include <cstddef>
#include <system_error>
@@ -55,10 +56,11 @@
#include <utility> // move()
#include <ostream>
-#ifdef _WIN32
+#ifndef _WIN32
+#include <thread> // this_thread::sleep_for()
+#else
#include <map>
#include <ratio> // milli
-#include <chrono>
#include <cstdlib> // __argv[]
#include <algorithm> // 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<bool> 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<bool> (*exit) : optional<bool> ();
+ }
+
+ template <>
+ optional<bool> 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<bool> 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<bool> (*exit) : optional<bool> ();
+ }
+
+ template <>
+ optional<bool> process::
+ timed_wait (const chrono::milliseconds&)
+ {
+ throw process_error (ENOTSUP);
+ }
+
+ void process::
+ kill ()
+ {
+ throw process_error (ENOTSUP);
}
process::id_type process::