VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gnewprocess.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 ///
18 /// \file gnewprocess.h
19 ///
20 
21 #ifndef G_NEW_PROCESS_H
22 #define G_NEW_PROCESS_H
23 #define G_NEW_PROCESS_WITH_WAIT_FUTURE
24 
25 #include "gdef.h"
26 #include "gexception.h"
27 #include "gidentity.h"
28 #include "gprocess.h"
29 #include "gpath.h"
30 #include "gstrings.h"
31 #include <string>
32 
33 namespace G
34 {
35  class NewProcess ;
36  class NewProcessImp ;
37  class NewProcessWaitFuture ;
38  class Pipe ;
39 }
40 
41 /// \class G::NewProcess
42 /// A class for creating new processes.
43 /// \see G::Daemon, G::NewProcess
44 ///
46 {
47 public:
48  G_EXCEPTION( CannotFork , "cannot fork()" ) ;
49  G_EXCEPTION( WaitError , "cannot wait()" ) ;
50  G_EXCEPTION( ChildError , "child process terminated abnormally or stopped" ) ;
51  G_EXCEPTION( Insecure , "refusing to exec() while the user-id is zero" ) ;
52  G_EXCEPTION( PipeError , "pipe error" ) ;
53  G_EXCEPTION( InvalidPath , "invalid executable path -- must be absolute" ) ;
54  G_EXCEPTION( CreateProcessError , "CreateProcess() error" ) ; // windows
55 
56  NewProcess( const Path & exe , const StringArray & args ,
57  int capture_stdxxx = 1 , bool clean = true , bool strict_path = true ,
58  Identity run_as_id = Identity::invalid() , bool strict_id = true ,
59  int exec_error_exit = 127 ,
60  const std::string & exec_error_format = std::string() ,
61  std::string (*exec_error_format_fn)(std::string,int) = 0 ) ;
62  ///< Constructor. Spawns the given program to run independently in a
63  ///< child process.
64  ///<
65  ///< The parent process can capture the child process's stdout or
66  ///< stderr (ie. stdxxx) by redirecting it to an internal pipe going
67  ///< from child to parent.
68  ///<
69  ///< The child process is optionally given a clean, minimalist
70  ///< environment.
71  ///<
72  ///< If 'strict_path' then the program must be given as an absolute path.
73  ///< Otherwise it can be relative and the PATH environment is used
74  ///< to find it. (The PATH search applies after the environment has
75  ///< been cleaned or not.)
76  ///<
77  ///< If a valid identity is supplied then the child process runs as
78  ///< that identity. If 'strict_id' is also true then the id is not
79  ///< allowed to be root. See Process::beOrdinaryForExec().
80  ///<
81  ///< By default the child process runs with stdin and stderr attached to
82  ///< the null device and stdout attached to the internal pipe. The
83  ///< internal pipe is also used for error messages in case the exec()
84  ///< fails.
85  ///<
86  ///< If the exec() fails then the 'exec_error_exit' argument is used as
87  ///< the child process exit code, and if either of the other 'exec_whatever'
88  ///< arguments is supplied then an exec error message is written into
89  ///< the child process's end of the internal pipe.
90  ///<
91  ///< The exec error message is assembled by the given callback function,
92  ///< with the 'exec_error_format' argument passed as its second parameter.
93  ///< The first parameter is the exec() errno. The default callback function
94  ///< does text substitution for "__errno__" and "__strerror__"
95  ///< substrings that appear within the error format string.
96 
97  ~NewProcess() ;
98  ///< Destructor. Kills the spawned process if the WaitFuture has
99  ///< not been resolved.
100 
102  ///< Returns a reference to the WaitFuture sub-object so that the caller
103  ///< can wait for the child process to exit.
104 
105  void kill() ;
106  ///< Tries to kill the spawned process.
107 
108  static std::pair<bool,pid_t> fork() ;
109  ///< A utility function that forks the calling process and returns
110  ///< twice; once in the parent and once in the child. Returns
111  ///< an "is-in-child/child-pid" pair.
112  /// \see G::Daemon
113 
114 private:
115  NewProcess( const NewProcess & ) ;
116  void operator=( const NewProcess & ) ;
117  static std::string execErrorFormat( const std::string & , int ) ;
118 
119 private:
120  NewProcessImp * m_imp ;
121 } ;
122 
123 /// \class G::NewProcessWaitFuture
124 /// A class that holds the parameters and the results of a waitpid() system
125 /// call. The run() method can be run from a worker thread and the results
126 /// collected by the main thread using get() once the worker thread has
127 /// signalled that it has finished. The signalling mechanism is outside the
128 /// scope of this class.
129 ///
131 {
132 public:
134  ///< Default constructor for an object where run() does nothing
135  ///< and get() returns zero.
136 
137  explicit NewProcessWaitFuture( HANDLE hprocess ) ;
138  ///< Constructor taking a process handle.
139 
140  explicit NewProcessWaitFuture( pid_t pid , int fd = -1 ) ;
141  ///< Constructor taking a posix process-id and optional
142  ///< readable file descriptor.
143 
145  ///< Waits for the process identified by the constructor
146  ///< parameter to exit. Returns *this. This method can be
147  ///< called from a separate worker thread.
148 
149  int get() ;
150  ///< Returns the result of the run() as either the process
151  ///< exit code or as a thrown exception. Typically called
152  ///< by the main thread after the run() worker thread has
153  ///< signalled its completion.
154 
155  std::string output() ;
156  ///< Returns the first bit of child-process output.
157  ///< Used after get().
158 
159 private:
160  std::vector<char> m_buffer ;
161  HANDLE m_hprocess ;
162  pid_t m_pid ;
163  int m_fd ;
164  int m_rc ;
165  int m_status ;
166  int m_error ;
167  int m_read_error ;
168 } ;
169 
170 #endif
void kill()
Tries to kill the spawned process.
static Identity invalid()
Returns an invalid identity.
A class that holds the parameters and the results of a waitpid() system call.
Definition: gnewprocess.h:130
A combination of user-id and group-id, with a very low-level interface to the get/set/e/uid/gid funct...
Definition: gidentity.h:42
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
NewProcess(const Path &exe, const StringArray &args, int capture_stdxxx=1, bool clean=true, bool strict_path=true, Identity run_as_id=Identity::invalid(), bool strict_id=true, int exec_error_exit=127, const std::string &exec_error_format=std::string(), std::string(*exec_error_format_fn)(std::string, int)=0)
Constructor.
static std::pair< bool, pid_t > fork()
A utility function that forks the calling process and returns twice; once in the parent and once in t...
~NewProcess()
Destructor.
std::string output()
Returns the first bit of child-process output.
NewProcessWaitFuture & run()
Waits for the process identified by the constructor parameter to exit.
NewProcessWaitFuture & wait()
Returns a reference to the WaitFuture sub-object so that the caller can wait for the child process to...
NewProcessWaitFuture()
Default constructor for an object where run() does nothing and get() returns zero.
A pimple-pattern implementation class used by G::NewProcess.
A Path object represents a file system path.
Definition: gpath.h:72
A class for creating new processes.
Definition: gnewprocess.h:45