4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
7 * \author Asger Alstrup
8 * \author Angus Leeming
9 * \author Alfredo Braunstein
11 * Full author contact details are available in file CREDITS.
17 #include "support/shared_ptr.h"
18 #include "support/strfwd.h"
19 #include <boost/signal.hpp>
21 #ifdef HAVE_SYS_TYPES_H
22 # include <sys/types.h>
41 virtual ~ForkedProcess() {}
43 virtual shared_ptr<ForkedProcess> clone() const = 0;
45 /** A SignalType signal can be emitted once the forked process
46 * has finished. It passes:
47 * the PID of the child and;
48 * the return value from the child.
50 * We use a signal rather than simply a callback function so that
51 * we can return easily to C++ methods, rather than just globally
52 * accessible functions.
54 typedef boost::signal<void(pid_t, int)> SignalType;
56 /** The signal is connected in the calling routine to the desired
57 * slot. We pass a shared_ptr rather than a reference to the signal
58 * because it is eminently possible for the instance of the calling
59 * class (and hence the signal) to be destructed before the forked
62 * It doesn't matter if the slot disappears, SigC takes care of that.
64 typedef shared_ptr<SignalType> SignalTypePtr;
66 /** Invoking the following methods makes sense only if the command
67 * is running asynchronously!
70 /** gets the PID of the child process.
73 pid_t pid() const { return pid_; }
80 /** Set the return value of the child process.
83 void setRetValue(int r) { retval_ = r; }
85 /// Returns the identifying command (for display in the GUI perhaps).
86 std::string const & command() const { return command_; }
88 /// is the process running ?
91 /** Kill child prematurely.
92 * First, a SIGHUP is sent to the child.
93 * If that does not end the child process within "tolerance"
94 * seconds, the SIGKILL signal is sent to the child.
95 * When the child is dead, the callback is called.
97 void kill(int tolerance = 5);
99 /// Returns true if this is a child process
100 static bool iAmAChild() { return IAmAChild; }
103 /** Spawn the child process.
104 * Returns returncode from child.
106 int run(Starttype type);
108 /// implement our own version of fork()
109 /// it just returns -1 if ::fork() is not defined
110 /// otherwise, it forks and sets the global child-process
111 /// boolean IAmAChild
114 /// Callback function
115 SignalTypePtr signal_;
117 /// identifying command (for display in the GUI perhaps).
118 std::string command_;
120 /// Process ID of child
123 /// Return value from child
126 /// generate child in background
127 virtual int generateChild() = 0;
130 static bool IAmAChild;
132 /// Wait for child process to finish. Updates returncode from child.
138 * An instance of class ForkedCall represents a single child process.
140 * Class ForkedCall uses fork() and execvp() to lauch the child process.
142 * Once launched, control is returned immediately to the parent process
143 * but a Signal can be emitted upon completion of the child.
145 * The child process is not killed when the ForkedCall instance goes out of
146 * scope, but it can be killed by an explicit invocation of the kill() member
150 class ForkedCall : public ForkedProcess {
153 ForkedCall(std::string const & path = empty_string());
155 virtual shared_ptr<ForkedProcess> clone() const {
156 return shared_ptr<ForkedProcess>(new ForkedCall(*this));
159 /** Start the child process.
161 * The command "what" is passed to execvp() for execution.
163 * There are two startScript commands available. They differ in that
164 * the second receives a signal that is executed on completion of
165 * the command. This makes sense only for a command executed
166 * in the background, ie DontWait.
168 * The other startscript command can be executed either blocking
169 * or non-blocking, but no signal will be emitted on finishing.
171 int startScript(Starttype, std::string const & what);
174 int startScript(std::string const & what, SignalTypePtr);
178 virtual int generateChild();
180 std::string cmd_prefix_;
185 * This interfaces a queue of forked processes. In order not to
186 * hose the system with multiple processes running simultaneously, you can
187 * request the addition of your process to this queue and it will be
188 * executed when its turn comes.
192 namespace ForkedCallQueue {
194 ForkedCall::SignalTypePtr add(std::string const & process);
195 /// Query whether the queue is running a forked process now.
202 * Control of child processes launched using fork() and execvp().
205 namespace ForkedCallsController {
207 /// Add a new child process to the list of controlled processes.
208 void addCall(ForkedProcess const &);
210 /** Those child processes that are found to have finished are removed
211 * from the list and their callback function is passed the final
214 void handleCompletedProcesses();
216 /** Kill this process prematurely and remove it from the list.
217 * The process is killed within tolerance secs.
218 * See forkedcall.[Ch] for details.
220 void kill(pid_t, int tolerance = 5);
222 } // namespace ForkedCallsController
226 // a wrapper for GetLastError() and FormatMessage().
227 std::string const getChildErrorMessage();
230 } // namespace support
233 #endif // FORKEDCALLS_H