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/signals.h"
18 #include "support/strfwd.h"
20 #ifdef HAVE_SYS_TYPES_H
21 # include <sys/types.h>
43 virtual ~ForkedProcess() {}
45 virtual std::shared_ptr<ForkedProcess> clone() const = 0;
47 /** A Signal signal can be emitted once the forked process
48 * has finished. It passes:
49 * the PID of the child and;
50 * the return value from the child.
52 * We use a signal rather than simply a callback function so that
53 * we can return easily to C++ methods, rather than just globally
54 * accessible functions.
56 typedef signal<void(pid_t, int)> sig;
57 typedef sig::slot_type slot;
59 /** The signal is connected in the calling routine to the desired
60 * slot. We pass a shared_ptr rather than a reference to the signal
61 * because it is eminently possible for the instance of the calling
62 * class (and hence the signal) to be destructed before the forked
65 * Use Slot::track or Signal::scoped_connection to ensure that the
66 * connection is closed before the slot expires.
68 typedef std::shared_ptr<sig> sigPtr;
70 /** Invoking the following methods makes sense only if the command
71 * is running asynchronously!
74 /** gets the PID of the child process.
77 pid_t pid() const { return pid_; }
84 /** Set the return value of the child process.
87 void setRetValue(int r) { retval_ = r; }
89 /// Returns the identifying command (for display in the GUI perhaps).
90 std::string const & command() const { return command_; }
92 /// is the process running ?
95 /** Kill child prematurely.
96 * First, a SIGHUP is sent to the child.
97 * If that does not end the child process within "tolerance"
98 * seconds, the SIGKILL signal is sent to the child.
99 * When the child is dead, the callback is called.
101 void kill(int tolerance = 5);
103 /// Returns true if this is a child process
104 static bool iAmAChild() { return IAmAChild; }
107 /** Spawn the child process.
108 * Returns returncode from child.
110 int run(Starttype type);
112 /// implement our own version of fork()
113 /// it just returns -1 if ::fork() is not defined
114 /// otherwise, it forks and sets the global child-process
115 /// boolean IAmAChild
118 /// Callback function
121 /// identifying command (for display in the GUI perhaps).
122 std::string command_;
124 /// Process ID of child
127 /// Return value from child
130 /// generate child in background
131 virtual int generateChild() = 0;
134 static bool IAmAChild;
136 /// Wait for child process to finish. Updates returncode from child.
142 * An instance of class ForkedCall represents a single child process.
144 * Class ForkedCall uses fork() and execvp() to launch the child process.
146 * Once launched, control is returned immediately to the parent process
147 * but a Signal can be emitted upon completion of the child.
149 * The child process is not killed when the ForkedCall instance goes out of
150 * scope, but it can be killed by an explicit invocation of the kill() member
154 class ForkedCall : public ForkedProcess {
157 ForkedCall(std::string const & path = empty_string(),
158 std::string const & lpath = empty_string());
160 std::shared_ptr<ForkedProcess> clone() const override {
161 return std::make_shared<ForkedCall>(*this);
164 /** Start the child process.
166 * The command "what" is passed to execvp() for execution. "$$s" is
167 * replaced accordingly by commandPrep().
169 * There are two startScript commands available. They differ in that
170 * the second receives a signal that is executed on completion of
171 * the command. This makes sense only for a command executed
172 * in the background, ie DontWait.
174 * The other startscript command can be executed either blocking
175 * or non-blocking, but no signal will be emitted on finishing.
177 int startScript(Starttype, std::string const & what);
180 int startScript(std::string const & what, sigPtr ptr);
184 int generateChild() override;
186 std::string cmd_prefix_;
191 * This interfaces a queue of forked processes. In order not to
192 * hose the system with multiple processes running simultaneously, you can
193 * request the addition of your process to this queue and it will be
194 * executed when its turn comes.
198 namespace ForkedCallQueue {
200 ForkedCall::sigPtr add(std::string const & process);
201 /// Query whether the queue is running a forked process now.
204 } // namespace ForkedCallQueue
208 * Control of child processes launched using fork() and execvp().
211 namespace ForkedCallsController {
213 /// Add a new child process to the list of controlled processes.
214 void addCall(ForkedProcess const &);
216 /** Those child processes that are found to have finished are removed
217 * from the list and their callback function is passed the final
220 void handleCompletedProcesses();
222 /** Kill this process prematurely and remove it from the list.
223 * The process is killed within tolerance secs.
224 * See forkedcall.[Ch] for details.
226 void kill(pid_t, int tolerance = 5);
228 } // namespace ForkedCallsController
232 // a wrapper for GetLastError() and FormatMessage().
233 std::string const getChildErrorMessage();
236 } // namespace support
239 #endif // FORKEDCALLS_H