]> git.lyx.org Git - lyx.git/blob - src/support/Forkedcall.h
remove lyxrc dependence from support/*
[lyx.git] / src / support / Forkedcall.h
1 // -*- C++ -*-
2 /**
3  * \file Forkedcall.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Asger Alstrup
8  *
9  * Interface cleaned up by
10  * \author Angus Leeming
11  *
12  * Full author contact details are available in file CREDITS.
13  *
14  * An instance of Class Forkedcall represents a single child process.
15  *
16  * Class Forkedcall uses fork() and execvp() to lauch the child process.
17  *
18  * Once launched, control is returned immediately to the parent process
19  * but a Signal can be emitted upon completion of the child.
20  *
21  * The child process is not killed when the Forkedcall instance goes out of
22  * scope, but it can be killed by an explicit invocation of the kill() member
23  * function.
24  */
25
26 #ifndef FORKEDCALL_H
27 #define FORKEDCALL_H
28
29 #include <boost/shared_ptr.hpp>
30 #include <boost/signal.hpp>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36
37 namespace lyx {
38 namespace support {
39
40 class ForkedProcess {
41 public:
42         ///
43         enum Starttype {
44                 ///
45                 Wait,
46                 ///
47                 DontWait
48         };
49
50         ///
51         ForkedProcess();
52         ///
53         virtual ~ForkedProcess() {}
54         ///
55         virtual boost::shared_ptr<ForkedProcess> clone() const = 0;
56
57         /** A SignalType signal is can be emitted once the forked process
58          *  has finished. It passes:
59          *  the PID of the child and;
60          *  the return value from the child.
61          *
62          *  We use a signal rather than simply a callback function so that
63          *  we can return easily to C++ methods, rather than just globally
64          *  accessible functions.
65          */
66         typedef boost::signal<void(pid_t, int)> SignalType;
67
68         /** The signal is connected in the calling routine to the desired
69          *  slot. We pass a shared_ptr rather than a reference to the signal
70          *  because it is eminently possible for the instance of the calling
71          *  class (and hence the signal) to be destructed before the forked
72          *  call is complete.
73          *
74          *  It doesn't matter if the slot disappears, SigC takes care of that.
75          */
76         typedef boost::shared_ptr<SignalType> SignalTypePtr;
77
78         /** Invoking the following methods makes sense only if the command
79          *  is running asynchronously!
80          */
81
82         /** gets the PID of the child process.
83          *  Used by the timer.
84          */
85         pid_t pid() const { return pid_; }
86
87         /** Emit the signal.
88          *  Used by the timer.
89          */
90         void emitSignal();
91
92         /** Set the return value of the child process.
93          *  Used by the timer.
94          */
95         void setRetValue(int r) { retval_ = r; }
96
97         /// Returns the identifying command (for display in the GUI perhaps).
98         std::string const & command() const { return command_; }
99
100         /// is the process running ?
101         bool running() const;
102
103         /** Kill child prematurely.
104          *  First, a SIGHUP is sent to the child.
105          *  If that does not end the child process within "tolerance"
106          *  seconds, the SIGKILL signal is sent to the child.
107          *  When the child is dead, the callback is called.
108          */
109         void kill(int tolerance = 5);
110
111 protected:
112         /** Spawn the child process.
113          *  Returns returncode from child.
114          */
115         int run(Starttype type);
116
117         /// Callback function
118         SignalTypePtr signal_;
119
120         /// identifying command (for display in the GUI perhaps).
121         std::string command_;
122
123         /// Process ID of child
124         pid_t pid_;
125
126         /// Return value from child
127         int retval_;
128 private:
129         /// generate child in background
130         virtual int generateChild() = 0;
131
132         /// Wait for child process to finish. Updates returncode from child.
133         int waitForChild();
134 };
135
136
137 class Forkedcall : public ForkedProcess {
138 public:
139         ///
140         virtual boost::shared_ptr<ForkedProcess> clone() const {
141                 return boost::shared_ptr<ForkedProcess>(new Forkedcall(*this));
142         }
143
144         /** Start the child process.
145          *
146          *  The command "what" is passed to execvp() for execution.
147          *
148          *  There are two startscript commands available. They differ in that
149          *  the second receives a signal that is executed on completion of
150          *  the command. This makes sense only for a command executed
151          *  in the background, ie DontWait.
152          *
153          *  The other startscript command can be executed either blocking
154          *  or non-blocking, but no signal will be emitted on finishing.
155          */
156         int startscript(Starttype, std::string const & what);
157
158         ///
159         int startscript(std::string const & what, SignalTypePtr);
160
161 private:
162         ///
163         virtual int generateChild();
164 };
165
166 } // namespace support
167 } // namespace lyx
168
169 #endif // FORKEDCALL_H