Set dependents desired state to STOPPED immediately
[oweals/dinit.git] / service.cc
1 #include "service.h"
2 #include <cstring>
3 #include <cerrno>
4 #include <sstream>
5 #include <iterator>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10
11 // Tokenize a string, allow quoting
12 // TODO doesn't yet allow quoting...
13 static std::vector<std::string> tokenize(std::string arg)
14 {
15     // TODO rewrite to be more efficient.
16     using namespace std;
17     istringstream iss(arg);
18     return vector<string>(istream_iterator<string>(iss), istream_iterator<string>());
19 }
20
21 // Find the requested service by name
22 static ServiceRecord * findService(const std::list<ServiceRecord *> & records,
23                                     const char *name)
24 {
25     using std::list;
26     list<ServiceRecord *>::const_iterator i = records.begin();
27     for ( ; i != records.end(); i++ ) {
28         if (strcmp((*i)->getServiceName(), name) == 0) {
29             return *i;
30         }
31     }
32     return (ServiceRecord *)0;
33 }
34
35 ServiceRecord * ServiceSet::findService(std::string name)
36 {
37     return ::findService(records, name.c_str());
38 }
39
40 void ServiceSet::startService(const char *name)
41 {
42     using namespace std;
43     ServiceRecord *record = loadServiceRecord(name);
44     
45     record->start();
46 }
47
48 void ServiceSet::stopService(const std::string & name)
49 {
50     ServiceRecord *record = findService(name);
51     if (record != nullptr) {
52         record->stop();
53     }
54 }
55
56 // Called when a service has actually stopped.
57 void ServiceRecord::stopped()
58 {
59     service_state = SVC_STOPPED;
60     force_stop = false;
61     
62     // Stop any dependencies whose desired state is SVC_STOPPED:
63     for (sr_iter i = depends_on.begin(); i != depends_on.end(); i++) {
64         (*i)->dependentStopped();
65     }
66
67     service_set->service_inactive(this);
68     
69     // TODO inform listeners.
70     if (desired_state == SVC_STARTED) {
71         // Desired state is "started".
72         start();
73     }
74 }
75
76 void ServiceRecord::process_child_callback(struct ev_loop *loop, ev_child *w, int revents)
77 {    
78     ServiceRecord *sr = (ServiceRecord *) w->data;
79
80     sr->pid = -1;
81     ev_child_stop(ev_default_loop(EVFLAG_AUTO), &sr->child_listener);
82     
83     // Ok, for a process service, any process death which we didn't rig
84     // ourselves is a bit... unexpected. Probably, the child died because
85     // we asked it to (sr->service_state == SVC_STOPPING). But even if
86     // we didn't, there's not much we can do.
87     
88     if (sr->service_type == SVC_PROCESS) {
89         // TODO log non-zero rstatus?
90         if (sr->service_state == SVC_STOPPING) {
91             sr->stopped();
92         }
93         else {
94             sr->forceStop();
95         }
96         
97         if (sr->auto_restart && sr->service_set->get_auto_restart()) {
98             sr->start();
99         }
100     }
101     else {  // SVC_SCRIPTED
102         if (sr->service_state == SVC_STOPPING) {
103             if (w->rstatus == 0) {
104                 sr->stopped();
105             }
106             else {
107                 // TODO
108                 // ??? failed to stop!
109                 // For now just pretend we stopped, so that any dependencies
110                 // can be stopped:
111                 sr->stopped();
112             }
113         }
114         else { // SVC_STARTING
115             if (w->rstatus == 0) {
116                 sr->started();
117             }
118             else {
119                 // failed to start
120                 sr->failed_to_start();
121             }
122         }
123     }
124 }
125
126 void ServiceRecord::start()
127 {
128     if ((service_state == SVC_STARTING || service_state == SVC_STARTED)
129             && desired_state == SVC_STOPPED) {
130         // This service was starting, or started, but was set to be stopped.
131         // Cancel the stop (and continue starting/running).
132         // TODO any listeners waiting for stop should be notified of
133         //      its cancellation
134     }
135     
136     desired_state = SVC_STARTED;
137
138     if (service_state != SVC_STOPPED) {
139         // Either we need do nothing (service is already started/starting)
140         // or the service is currently being stopped and we must wait for
141         // that to complete.
142         return;
143     }
144     
145     // Service state is SVC_STOPPED. Start the service.
146     
147     // First, start dependencies
148     bool all_deps_started = true;
149     for (sr_iter i = depends_on.begin(); i != depends_on.end(); ++i) {
150         // Note, we cannot treat a dependency as started if its force_stop
151         // flag is set.
152         if ((*i)->service_state != SVC_STARTED || (*i)->force_stop) {
153             all_deps_started = false;
154             (*i)->start();
155         }
156     }
157     
158     if (! all_deps_started) {
159         // The dependencies will notify this service once they've started.
160         return;
161     }
162     
163     // Actually start this service.
164     service_state = SVC_STARTING;
165     service_set->service_active(this);
166     
167     if (service_type == SVC_PROCESS) {
168         bool start_success = start_ps_process();
169         if (start_success) {
170             started();
171         }
172         else {
173             failed_to_start();
174         }
175     }
176     else {
177         // Script-controlled service
178         bool start_success = start_ps_process(std::vector<std::string>(1, "start"));
179         if (! start_success) {
180             failed_to_start();
181         }
182     }
183 }
184
185 void ServiceRecord::started()
186 {
187     service_state = SVC_STARTED;
188     // TODO - inform listeners
189
190     if (desired_state == SVC_STARTED) {
191         // Start any dependents whose desired state is SVC_STARTED:
192         for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
193             if ((*i)->desired_state == SVC_STARTED) {
194                 (*i)->start();
195             }
196         }
197         for (sr_iter i = soft_dependents.begin(); i != soft_dependents.end(); i++) {
198             if ((*i)->desired_state == SVC_STARTED) {
199                 (*i)->start();
200             }
201         }
202     }
203     else {
204         stop();
205     }
206 }
207
208 void ServiceRecord::failed_to_start()
209 {
210     service_state = SVC_STOPPED;
211     desired_state = SVC_STOPPED;
212     service_set->service_inactive(this);
213     // failure to start
214     // Cancel start of dependents:
215     for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
216         if ((*i)->desired_state == SVC_STARTED) {
217             (*i)->failed_dependency();
218         }
219     }    
220     // What about soft dependents?
221     // TODO we should probably send them "start" rather than "failed_dependency",
222     // or add a parameter to failed_dependency which says whether the dependency
223     // was soft and change start handling as appropriate.
224     // For now just fail the startup:
225     for (sr_iter i = soft_dependents.begin(); i != soft_dependents.end(); i++) {
226         if ((*i)->desired_state == SVC_STARTED) {
227             (*i)->failed_dependency();
228         }
229     }
230 }
231
232 bool ServiceRecord::start_ps_process()
233 {
234     return start_ps_process(std::vector<std::string>());
235 }
236
237
238 bool ServiceRecord::start_ps_process(const std::vector<std::string> &pargs)
239 {
240     // In general, you can't tell whether fork/exec is successful. We use a pipe to communicate
241     // success/failure from the child to the parent. The pipe is set CLOEXEC so a successful
242     // exec closes the pipe, and the parent sees EOF. If the exec is unsuccessful, the errno
243     // is written to the pipe, and the parent can read it.
244     
245     using std::vector;
246     using std::string;
247     
248     int pipefd[2];
249     if (pipe2(pipefd, O_CLOEXEC)) {
250         // TODO log error
251         return false;
252     }
253     
254     // TODO make sure pipefd's are not 0/1/2 (STDIN/OUT/ERR) - if they are, dup them
255     // until they are not.
256     
257     pid_t forkpid = fork();
258     if (forkpid == -1) {
259         // TODO log error
260         close(pipefd[0]);
261         close(pipefd[1]);
262         return false;
263     }
264     
265     if (forkpid == 0) {
266         // Child process
267         ev_default_destroy(); // won't need that on this side, free up fds.
268         
269         // Re-set stdin, stdout, stderr
270         close(0); close(1); close(2);
271         string logfile = this->logfile;
272         if (logfile.length() == 0) {
273             logfile = "/dev/null";
274         }
275         
276         // TODO rethink this logic. If we open it at not-0, shouldn't we just dup it to 0?:
277         if (open("/dev/null", O_RDONLY) == 0) {
278           // stdin = 0. That's what we should have; proceed with opening
279           // stdout and stderr.
280           open(logfile.c_str(), O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
281           dup2(1, 2);
282         }
283         
284         // Tokenize the command, and add additional arguments from pargs:
285         vector<string> progAndArgs = tokenize(program_name);
286         progAndArgs.insert(progAndArgs.end(), pargs.begin(), pargs.end());
287        
288         const char * pname = progAndArgs[0].c_str();
289         const char ** args = new const char *[progAndArgs.size() + 1];
290         
291         for (std::vector<std::string>::size_type i = 0; i < progAndArgs.size(); i++) {
292             args[i] = progAndArgs[i].c_str();
293         }
294         args[progAndArgs.size()] = nullptr;
295         
296         execvp(pname, (char ** const) args);
297         
298         // If we got here, the exec failed:        
299         int exec_status = errno;
300         write(pipefd[1], &exec_status, sizeof(int));
301         exit(0);
302     }
303     else {
304         // Parent process - we only reach here once the exec() above
305         // has succeeded, or _exit() above was called (because vfork()
306         // suspends the parent until either of those occurs).
307         
308         close(pipefd[1]); // close the 'other end' fd
309
310         int exec_status;        
311         if (read(pipefd[0], &exec_status, sizeof(int)) == 0) {
312             // pipe closed; success
313             pid = forkpid;
314
315             // Add a process listener so we can detect when the
316             // service stops
317             ev_child_init(&child_listener, process_child_callback, pid, 0);
318             child_listener.data = this;
319             ev_child_start(ev_default_loop(EVFLAG_AUTO), &child_listener);
320
321             close(pipefd[0]);
322             return true;
323         }
324         else {
325             // TODO log error
326             close(pipefd[0]);
327             return false;
328         }
329     }
330 }
331
332
333
334
335 // Mark this and all dependent services as force-stopped.
336 void ServiceRecord::forceStop()
337 {
338     force_stop = true;
339     stop();
340     for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
341         (*i)->forceStop();
342     }
343     // We don't want to force stop soft dependencies, however.
344 }
345
346 // A dependency of this service failed to start.
347 void ServiceRecord::failed_dependency()
348 {
349     desired_state = SVC_STOPPED;
350     
351     // Presumably, we were starting. So now we're not.
352     service_state = SVC_STOPPED;
353     
354     // Notify dependents of this service also
355     for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
356         if ((*i)->desired_state == SVC_STARTED) {
357             (*i)->failed_dependency();
358         }
359     }
360     for (sr_iter i = soft_dependents.begin(); i != soft_dependents.end(); i++) {
361         if ((*i)->desired_state == SVC_STARTED) {
362             (*i)->failed_dependency();
363         }
364     }    
365 }
366
367 void ServiceRecord::dependentStopped()
368 {
369     if (service_state != SVC_STOPPED && (desired_state == SVC_STOPPED || force_stop)) {
370         // Check the other dependents before we stop.
371         if (stopCheckDependents()) {
372             stopping();
373         }
374     }
375 }
376
377 void ServiceRecord::stop()
378 {
379     if ((service_state == SVC_STOPPING || service_state == SVC_STOPPED)
380             && desired_state == SVC_STARTED) {
381         // The service *was* stopped/stopping, but it was going to restart.
382         // Now, we'll cancel the restart.
383         // TODO inform listeners waiting for start of cancellation
384     }
385     
386     if (desired_state == SVC_STOPPED) return;
387     
388     desired_state = SVC_STOPPED;
389
390     if (service_state != SVC_STARTED) {
391         if (service_state == SVC_STARTING) {
392             // Well this is awkward: we're going to have to continue
393             // starting, but we don't want any dependents to think that
394             // they are still waiting to start.
395             // Make sure they remain stopped:
396             stopDependents();
397         }
398         
399         // If we're starting we need to wait for that to complete.
400         // If we're already stopping/stopped there's nothing to do.
401         return;
402     }
403     
404     // If we get here, we are in STARTED state; stop all dependents.
405     if (stopCheckDependents()) {
406         stopping();
407     }
408 }
409
410 bool ServiceRecord::stopCheckDependents()
411 {
412     bool all_deps_stopped = true;
413     for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
414         if ((*i)->service_state != SVC_STOPPED) {
415             all_deps_stopped = false;
416             break;
417         }
418     }
419     
420     return all_deps_stopped;
421 }
422
423 bool ServiceRecord::stopDependents()
424 {
425     bool all_deps_stopped = true;
426     for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
427         if ((*i)->service_state != SVC_STOPPED) {
428             all_deps_stopped = false;
429             (*i)->stop();
430         }
431     }
432     
433     return all_deps_stopped;
434 }
435
436
437
438 // Dependency stopped or is stopping; we must stop too.
439 void ServiceRecord::stopping()
440 {
441     service_state = SVC_STOPPING;
442
443     if (service_type == SVC_PROCESS) {
444         if (pid != -1) {
445           // The process is still kicking on - must actually kill it.
446           kill(pid, SIGTERM);
447           // Now we wait; the rest is done in process_child_callback
448         }
449         else {
450             // The process is already dead.
451             stopped();
452         }
453     }
454     else {
455         // Scripted service.
456         start_ps_process(std::vector<string>(1, "stop"));
457     }    
458 }
459
460 void ServiceSet::service_active(ServiceRecord *sr)
461 {
462     active_services++;
463 }
464
465 void ServiceSet::service_inactive(ServiceRecord *sr)
466 {
467     active_services--;
468 }