]> git.lyx.org Git - lyx.git/blob - src/support/syscontr.C
lyxserver cleanup patch + andre's small patches
[lyx.git] / src / support / syscontr.C
1 #include <config.h>
2
3 #include <cerrno>
4 #include <cstdlib>
5 #include <unistd.h>
6 #include <sys/wait.h>
7 #include "syscontr.h"
8 #include "syscall.h"
9 #include "debug.h"
10
11 #ifdef __GNUG__
12 #pragma implementation
13 #endif
14
15
16 using std::endl;
17
18 #ifndef CXX_GLOBAL_CSTD
19 using std::strerror;
20 #endif
21
22 //
23 // Default constructor
24 //
25
26 SystemcallsSingletoncontroller::SystemcallsSingletoncontroller() 
27 {
28        sysCalls = 0;
29 }
30
31 //
32 // Destructor
33 // 
34 // destroy structs for leaving program
35 // open question: should we stop childs here?
36 // Asger says no: I like to have my xdvi open after closing LyX. Maybe
37 // I want to print or something.
38
39 SystemcallsSingletoncontroller::~SystemcallsSingletoncontroller()
40 {
41        ControlledCalls *next;
42        while (sysCalls)
43        {
44                next = sysCalls->next;
45                delete sysCalls;
46                sysCalls = next;
47        }
48        
49 }
50
51 //
52 // Add child process information into controlled list
53 //
54
55 void 
56 SystemcallsSingletoncontroller::addCall(Systemcalls const &newcall) {
57        ControlledCalls * newCall = new ControlledCalls;
58        if (newCall == 0) // sorry, no idea
59                return;
60        newCall->next = sysCalls;
61        newCall->call = new Systemcalls(newcall);
62        sysCalls = newCall;
63 }
64
65 // 
66 // Timer-call
67 // 
68 // Check list, if there is a stopped child. If yes, call-back.
69 //
70
71 void 
72 SystemcallsSingletoncontroller::timer() {
73         lyxerr << "Tick" << endl;
74         // check each entry of our list, if it's finished
75         ControlledCalls *prev = 0;
76         for (ControlledCalls *actCall= sysCalls; actCall; actCall= actCall->next)
77         {
78                 pid_t pid= actCall->call->getpid();
79                 int stat_loc;
80                 int waitrpid = waitpid(pid, &stat_loc, WNOHANG);
81                 if (waitrpid == -1) {
82                         lyxerr << "LyX: Error waiting for child:" 
83                                << strerror(errno) << endl;
84                 } else if (WIFEXITED(stat_loc) || WIFSIGNALED(stat_loc)) {
85                         if (WIFEXITED(stat_loc)) {
86                                 // Ok, the return value goes into retval.
87                                 actCall->call->setRetValue(WEXITSTATUS(stat_loc));
88                         } else {
89                                 // Child died, so pretend it returned 1
90                                 actCall->call->setRetValue(1);
91                         }
92                         // Callback and release
93                         actCall->call->callback();
94                         if (actCall == sysCalls) {
95                                 sysCalls = actCall->next;
96                         } else {
97                                 prev->next = actCall->next;
98                         }
99                         delete actCall;
100                         actCall = prev;
101                 } else if (WIFSTOPPED(stat_loc)) {
102                         lyxerr << "LyX: Child (pid: " << pid 
103                                << ") stopped on signal "
104                                << WSTOPSIG(stat_loc) 
105                                << ". Waiting for child to finish." << endl;
106                 } else {
107                         lyxerr << "LyX: Something rotten happened while "
108                                 "waiting for child " << pid << endl;
109                 }
110                 prev = actCall;
111         }
112 }