From a128eb0961ccf820ff2142897795b48723d842bd Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 21 Oct 2016 20:02:35 +0300 Subject: Make process status optional --- butl/pager.cxx | 4 ++++ butl/process | 32 ++++++++++++++++++-------------- butl/process.cxx | 35 +++++++++++++++++++---------------- butl/process.ixx | 6 +++--- 4 files changed, 44 insertions(+), 33 deletions(-) (limited to 'butl') diff --git a/butl/pager.cxx b/butl/pager.cxx index 3d429f5..b154a5c 100644 --- a/butl/pager.cxx +++ b/butl/pager.cxx @@ -28,6 +28,10 @@ namespace butl bool verbose, const string* pager, const vector* pager_options) + // Create successfully exited process. Will "wait" for it if fallback to + // non-interactive execution path. + // + : p_ (optional (0)) { // If we are using the default pager, try to get the terminal width // so that we can center the output. diff --git a/butl/process b/butl/process index e1eea29..c69c306 100644 --- a/butl/process +++ b/butl/process @@ -16,6 +16,7 @@ #include #include +#include namespace butl { @@ -106,6 +107,16 @@ namespace butl class LIBBUTL_EXPORT process { public: +#ifndef _WIN32 + using handle_type = pid_t; + using id_type = pid_t; + using status_type = int; +#else + using handle_type = void*; // Win32 HANDLE + using id_type = std::uint32_t; // Win32 DWORD + using status_type = std::uint32_t; // Win32 DWORD +#endif + // Start another process using the specified command line. The default // values to the in, out and err arguments indicate that the child process // should inherit the parent process stdin, stdout, and stderr, @@ -202,10 +213,13 @@ namespace butl process (const process&) = delete; process& operator= (const process&) = delete; - // Create an empty or "already terminated" process. That is, handle is 0 - // and exit status is 0. + // Create an empty or "already terminated" process. By default the + // termination status is abnormal but you can change that. + // + // @@ Need to audit all calls (__attribute__((deprecated))). // - process (); + explicit + process (optional status = nullopt); // Resolve process' paths based on the initial path in args0. If recall // differs from initial, adjust args0 to point to the recall path. If @@ -274,22 +288,12 @@ namespace butl print (std::ostream&, const char* const args[], size_t n = 0); public: -#ifndef _WIN32 - using handle_type = pid_t; - using id_type = pid_t; - using status_type = int; -#else - using handle_type = void*; // Win32 HANDLE - using id_type = std::uint32_t; // Win32 DWORD - using status_type = std::uint32_t; // Win32 DWORD -#endif - static id_type current_id (); public: handle_type handle; - status_type status; + optional status; // Absence means terminated abnormally. int out_fd; // Write to this fd to send to the new process' stdin. int in_ofd; // Read from this fd to receive from the new process' stdout. diff --git a/butl/process.cxx b/butl/process.cxx index 64366ba..3af42cf 100644 --- a/butl/process.cxx +++ b/butl/process.cxx @@ -385,25 +385,23 @@ namespace butl { if (handle != 0) { - int r (waitpid (handle, &status, 0)); + status_type es; + int r (waitpid (handle, &es, 0)); handle = 0; // We have tried. if (r == -1) { + // If ignore errors then just leave status nullopt, so it has the same + // semantics as for abnormally terminated process. + // if (!ie) throw process_error (errno, false); - else - // Fold into status, so this and subsequent wait() calls return - // false. There is no portable way to update the status bits - // representing a process exit code specifically. So we set all bits - // to 1 and recon on getting non-zero exit status wherever the exact - // bits are. - // - status = ~0; } + else if (WIFEXITED (es)) + status = WEXITSTATUS (es); } - return WIFEXITED (status) && WEXITSTATUS (status) == 0; + return status && *status == 0; } bool process:: @@ -411,7 +409,8 @@ namespace butl { if (handle != 0) { - int r (waitpid (handle, &status, WNOHANG)); + status_type es; + int r (waitpid (handle, &es, WNOHANG)); if (r == 0) // Not exited yet. return false; @@ -420,9 +419,12 @@ namespace butl if (r == -1) throw process_error (errno, false); + + if (WIFEXITED (es)) + status = WEXITSTATUS (es); } - s = WIFEXITED (status) && WEXITSTATUS (status) == 0; + s = status && *status == 0; return true; } @@ -890,14 +892,15 @@ namespace butl status = s; else { + // If ignore errors then just leave status nullopt, so it has the same + // semantics as for abnormally terminated process. + // if (!ie) throw process_error (error_msg (e)); - else - status = 1; // Fold into status. } } - return status == 0; + return status && *status == 0; } bool process:: @@ -923,7 +926,7 @@ namespace butl status = s; } - s = status == 0; + s = status && *status == 0; return true; } diff --git a/butl/process.ixx b/butl/process.ixx index 83918bf..6d4dd2f 100644 --- a/butl/process.ixx +++ b/butl/process.ixx @@ -100,9 +100,9 @@ namespace butl } inline process:: - process () + process (optional s) : handle (0), - status (0), // This is a bit of an assumption. + status (s), out_fd (-1), in_ofd (-1), in_efd (-1) @@ -155,7 +155,7 @@ namespace butl wait (); handle = p.handle; - status = p.status; + status = std::move (p.status); out_fd = p.out_fd; in_ofd = p.in_ofd; in_efd = p.in_efd; -- cgit v1.1