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