From fc42391710a456594fb949f14b50e0d3d5cdc805 Mon Sep 17 00:00:00 2001 From: Venelin Date: Wed, 10 Jul 2024 17:14:35 +0300 Subject: [PATCH] add check_exited, exit on waitpid errors --- src/childProcess.hpp | 16 ++++++++++------ src/childProcess.inl | 41 ++++++++++++++++++++++++++++++++++------- src/commands.hpp | 16 ++++++++-------- src/commands.inl | 18 +++++++++--------- todo.txt | 3 +-- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/childProcess.hpp b/src/childProcess.hpp index ab9b08d..4289d11 100644 --- a/src/childProcess.hpp +++ b/src/childProcess.hpp @@ -1,6 +1,7 @@ #pragma once #include "basicTypes.h" +#include struct Proc { @@ -10,20 +11,23 @@ struct Proc fd_t err; }; -struct RetProc: public Proc /* returned process */ +/* process that has finished for any reason */ +struct DeadProc: public Proc { - RetProc(Proc, int status); /* status as returned by waitpid */ + DeadProc(Proc, int status); /* status as returned by waitpid */ bool normal_exit; - U8 returned; /* return code */ + U8 exit_status; /* only use if normal_exit */ /* A returned process evaluates to true if it exited normaly and * returned 0 */ explicit operator bool(); - }; -// Wait for a running proccess to finish -RetProc wait(Proc); +/* Wait for a running proccess to finish */ +DeadProc wait(Proc); + +/* Check if the Proc has exited and return it's DeadProc if it has */ +std::optional check_exited(Proc); enum Redirect: U32 { diff --git a/src/childProcess.inl b/src/childProcess.inl index c941cd0..9a0186b 100644 --- a/src/childProcess.inl +++ b/src/childProcess.inl @@ -6,22 +6,49 @@ #include "childProcess.hpp" -inline RetProc::RetProc(Proc origin, int status) +inline DeadProc::DeadProc(Proc origin, int status) : Proc(origin) , normal_exit(WIFEXITED(status)) - , returned(WEXITSTATUS(status)) + , exit_status(WEXITSTATUS(status)) {} -inline RetProc::operator bool() +inline DeadProc::operator bool() { - return normal_exit && returned == 0; + return normal_exit && exit_status == 0; } -inline RetProc wait(Proc p) +inline DeadProc wait(Proc p) { int status; - waitpid(p.pid, &status, 0); - return RetProc(p, status); + if( waitpid(p.pid, &status, 0) == -1 ) + { + std::cerr << "waitpid encountered an error: " << strerror(errno) << std::endl; + exit(1); + } + return DeadProc(p, status); +} + +inline std::optional check_exited(Proc p) +{ + std::optional result; + + int status; + pid_t rc = waitpid(p.pid, &status, WNOHANG); + if(rc == 0) // still running + { + result = std::nullopt; + } + else if(rc == -1) // waitpid error + { + std::cerr << "waitpid encountered an error: " << strerror(errno) << std::endl; + exit(1); + } + else // finished + { + result = DeadProc(p, status); + } + + return result; } namespace _cppipe diff --git a/src/commands.hpp b/src/commands.hpp index fe64632..f5c69de 100644 --- a/src/commands.hpp +++ b/src/commands.hpp @@ -26,7 +26,7 @@ public: /* Execute the command, if arguments are not given use stdin,out,err else use the given file desciptors. this can also be used to redirect err to out by giving err=1 like in shell */ - RetProc operator()(fd_t in=0, fd_t out=1, fd_t err=2); + DeadProc operator()(fd_t in=0, fd_t out=1, fd_t err=2); /* Run the command, don't wait to return like shell's & */ Proc detach(fd_t in=0, fd_t out=1, fd_t err=2); @@ -57,7 +57,7 @@ public: PendingCmd& operator=(const PendingCmd&) = delete; /* Run the command */ - RetProc operator()(); + DeadProc operator()(); /* Run the command async shell: cmd & @@ -90,12 +90,12 @@ void exec(const Cmd&); /* todo: take Pending? */ cd; */ PendingCmd operator,(const PendingCmd&, const Cmd&); -PendingCmd operator,(RetProc, const Cmd&); +PendingCmd operator,(DeadProc, const Cmd&); /* Forbiden funcion to prevent wrong sequencing such as: echo, echo && echo here the 2nd and 3rd echos would be ran before 1st due to the C++ operator precedence*/ -PendingCmd operator,(const PendingCmd&, RetProc) = delete; +PendingCmd operator,(const PendingCmd&, DeadProc) = delete; /* Shell pipe operator | - execute two commands, second takes input @@ -103,15 +103,15 @@ PendingCmd operator,(const PendingCmd&, RetProc) = delete; PendingCmd operator|(const PendingCmd&, const Cmd&); /* Shell operator && - run the second command only if first returns 0 (no errors)*/ -RetProc operator&&(const PendingCmd&, const Cmd&); -RetProc operator&&(RetProc, const Cmd&); +DeadProc operator&&(const PendingCmd&, const Cmd&); +DeadProc operator&&(DeadProc, const Cmd&); /* Shell operator || - run second only if first returns != 0 Operator precedence is different from shell, C precendence is && > || so mixing || and && may not compile, but shouldn't cause other issues, use () to resolve these cases */ -RetProc operator||(const PendingCmd&, const Cmd&); -RetProc operator||(RetProc, const Cmd&); +DeadProc operator||(const PendingCmd&, const Cmd&); +DeadProc operator||(DeadProc, const Cmd&); /* Shell operator > - redirect output to file shell: cmd > file 2>&1 diff --git a/src/commands.inl b/src/commands.inl index 1e83b6f..7cb1dd5 100644 --- a/src/commands.inl +++ b/src/commands.inl @@ -28,7 +28,7 @@ namespace _cppipe } } -inline RetProc Cmd::operator()(fd_t in, fd_t out, fd_t err) +inline DeadProc Cmd::operator()(fd_t in, fd_t out, fd_t err) { Proc p = createProcess(argv.data(), in, out, err); @@ -93,7 +93,7 @@ inline PendingCmd::~PendingCmd() /* close(err); */ } -inline RetProc PendingCmd::operator()() +inline DeadProc PendingCmd::operator()() { assert(!execed_ && "Executed command twice"); execed_ = true; @@ -161,7 +161,7 @@ inline PendingCmd operator,(const PendingCmd& cfirst, const Cmd& second) return PendingCmd(second); } -inline PendingCmd operator,(RetProc, const Cmd& second) +inline PendingCmd operator,(DeadProc, const Cmd& second) { return PendingCmd(second); } @@ -174,11 +174,11 @@ inline PendingCmd operator|(const PendingCmd& cfirst, const Cmd& second) } -inline RetProc operator&&(const PendingCmd& cfirst, const Cmd& csecond) +inline DeadProc operator&&(const PendingCmd& cfirst, const Cmd& csecond) { auto& first = const_cast(cfirst); auto& second = const_cast(csecond); - RetProc firstProc = first(); + DeadProc firstProc = first(); if(firstProc) return second(); @@ -186,7 +186,7 @@ inline RetProc operator&&(const PendingCmd& cfirst, const Cmd& csecond) return firstProc; } -inline RetProc operator&&(RetProc p, const Cmd& ccmd) +inline DeadProc operator&&(DeadProc p, const Cmd& ccmd) { auto& cmd = const_cast(ccmd); if(p) @@ -195,11 +195,11 @@ inline RetProc operator&&(RetProc p, const Cmd& ccmd) return p; } -inline RetProc operator||(const PendingCmd& cfirst, const Cmd& csecond) +inline DeadProc operator||(const PendingCmd& cfirst, const Cmd& csecond) { auto& first = const_cast(cfirst); auto& second = const_cast(csecond); - RetProc firstProc = first(); + DeadProc firstProc = first(); if(!firstProc) return second(); @@ -207,7 +207,7 @@ inline RetProc operator||(const PendingCmd& cfirst, const Cmd& csecond) return firstProc; } -inline RetProc operator||(RetProc p, const Cmd& ccmd) +inline DeadProc operator||(DeadProc p, const Cmd& ccmd) { auto& cmd = const_cast(ccmd); if(!p) diff --git a/todo.txt b/todo.txt index 91ea4b6..c4c3f27 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,5 @@ man -tips -openBSD support +tips (sigaction SIGCHILD, SIG_IGN, SIG_DFL) ? precompiled header cppipe.h