Properly fix the license for C++ template usage. This means we needed to change from...
[libasyncio] / asyncio / async_process.hpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /** @file
21  *
22  * simple process handling based on simple io classes.
23  *
24  * (c) Copyright 2007-2008 by Intra2net AG
25  */
26
27 #ifndef __ASYNC_PROCESS_HPP__
28 #define __ASYNC_PROCESS_HPP__
29
30 #include <vector>
31 #include <utility>
32
33 #include <sys/types.h>
34
35 #include <containerfunc.hpp>
36 #include <signalfunc.hpp>
37 #include "async_io.hpp"
38
39
40 namespace AsyncIo
41 {
42
43 using SystemTools::Signal;
44 using SystemTools::ScopedSignalBlocker;
45
46
47 class ProcessManager;
48
49
50 typedef std::pair< pid_t, int >      PidStatePair;
51 typedef std::vector< PidStatePair >  PidStateList;
52
53
54 /**
55  * represents process states.
56  */
57 struct ProcessState
58 {
59    enum _ProcessState
60    {
61       stopped = 0,
62       running,
63       suspended
64    }; // eo enum _ProcessState
65
66    _ProcessState m_state;
67
68    ProcessState(_ProcessState _state = stopped) : m_state(_state) {}
69
70    operator _ProcessState() const { return m_state; }
71 }; // eo struct ProcessState
72
73
74 /**
75  * specialisation of the io implementation class which fork/exec's a subprocess and
76  * connects with the new child's stdin/stdout.
77  *
78  * @note the signal @a IOImplementation::m_signal_eof of the base class can be used to detect when the
79  * new child closes it's stdout (which usually means that the child ended).
80  */
81 class ProcessImplementation : public IOImplementation
82 {
83       typedef IOImplementation inherited;
84
85       friend class ProcessManager;
86
87    public:
88
89       enum StderrMode
90       {
91          /// "magic" constant to pass to start() when childs stderr should be the same as parents stderr.
92          UseParentsStderr= 0,
93          /// "magic" constant to pass to start() when stderr should be the same as stdout for the new process.
94          StderrOnStdout
95       }; // eo enum StderrMode
96
97    public:
98       ProcessImplementation(
99          const std::string& path,
100          const std::vector<std::string>& args = std::vector<std::string>());
101       virtual ~ProcessImplementation();
102
103       virtual void close(Direction direction = Direction::both);
104
105       virtual bool startProcess( IOImplementation2* stderr );
106       bool startProcess( StderrMode stderr_mode = UseParentsStderr );
107
108       virtual void stopProcess(bool force=false);
109
110       PushBackFiller<std::string, std::vector > getArgAdder();
111
112       bool setCreateNewSession( bool enable= true);
113
114       bool setNice(int nice);
115
116       bool setWorkDir(const std::string& workdir);
117
118       void resetArgs( const std::vector< std::string >& args = std::vector< std::string >() );
119
120       /// returns the current process state
121       ProcessState processState() const { return m_state; }
122
123       ///returns the exit code of the process (if in stopped state)
124       int exitCode() const { return m_exit_code; }
125
126
127    protected:
128
129       bool kill(const Signal signal);
130
131       void setChildState(pid_t pid, int status);
132
133    protected:
134       /// the path to the binary
135       std::string m_path;
136       /// argument list (starting with argv0, usually the name of the binary)
137       std::vector<std::string> m_args;
138       /// increment of the nice level when the new child is started
139       int  m_nice_inc;
140       /// determines if the child should start a new session.
141       bool m_create_new_session;
142       /// determines the workdir where the child process should be started with.
143       std::string m_workdir;
144
145       /// the pid of the child process
146       pid_t m_pid;
147       /// the state of the child process
148       ProcessState m_state;
149       /// the exit code of the child (-1 if not available yet)
150       int  m_exit_code;
151
152       /// signal which is fired when the child terminated
153       SignalType m_signal_terminated;
154
155
156       /// "magic" constant to pass to start() when childs stderr should be the same as parents stderr.
157       static IOImplementation2* _UseParentsStderr;
158       /// "magic" constant to pass to start() when stderr should be the same as stdout for the new process.
159       static IOImplementation2* _StderrOnStdout;
160
161    private:
162
163 }; // eo class ProcessImplementation
164
165
166 /**
167  * manages overall process related stuff.
168  *
169  * @note this class is implemented as a singleton.
170  * @note this class uses the io timer interface to be called within the backend loops when necessary.
171  */
172 class ProcessManager : public TimerBase
173 {
174    public:
175
176       static ProcessManager* getInstance();
177
178    protected:
179       ProcessManager();
180       ProcessManager(const ProcessManager&);
181
182       virtual void execute();
183
184       void activateMe();
185
186    public:
187
188       /**
189        * the signal which is fired when waitpid() returns a status for a child process
190        * which is not managed by this process subsystem.
191        * Another module which forks child processes can connect to this signal to receive
192        * the information when these child processes are terminated.
193        */
194       boost::signal<void(pid_t,int)> m_foreign_child_state_changed_signal;
195
196    protected:
197
198       static ProcessManager *the_instance;
199
200       PidStateList  m_foreign_pid_states;
201
202    private:
203 };
204
205
206 bool installChildHandler();
207 bool restoreChildHandler();
208
209
210 } // eo namespace AsyncIo
211
212 #endif