Fix comment in relation to vfork (we are using fork instead now)
[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     auto old_desired_state = desired_state;
137     desired_state = SVC_STARTED;
138     
139     if (service_state == SVC_STARTED || service_state == SVC_STARTING) {
140         // We couldn't be started or starting unless all dependencies have
141         // already started: so there's nothing left to do.
142         return;
143     }
144     
145     bool all_deps_started = true;
146
147     // Ask dependencies to start, mark them as being waited on.
148     
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 (old_desired_state != SVC_STARTED) {
159         // This is a fresh start, so we mark all soft dependencies as 'waiting on' and ask them
160         // to start:
161         for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
162             if (i->getTo()->service_state != SVC_STARTED) {
163                 all_deps_started = false;
164                 i->getTo()->start();
165                 i->waiting_on = true;
166             }
167         }
168     }
169     else {
170         // This is (or at least may be) a notification that a dependency is ready; let's
171         // just check them:
172         for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
173             ServiceRecord * to = i->getTo();
174             if (i->waiting_on) {
175                 if ((to->desired_state != SVC_STARTED && to->service_state != SVC_STARTING) || to->service_state == SVC_STARTED) {
176                     // Service has either started or is no longer starting
177                     i->waiting_on = false;
178                 }
179                 else {
180                     all_deps_started = false;
181                 }
182             }
183         }
184     }
185     
186
187     if (! all_deps_started) {
188         // The dependencies will notify this service once they've started.
189         return;
190     }
191     
192     // Actually start this service.
193     service_state = SVC_STARTING;
194     service_set->service_active(this);
195     
196     if (service_type == SVC_PROCESS) {
197         bool start_success = start_ps_process();
198         if (start_success) {
199             started();
200         }
201         else {
202             failed_to_start();
203         }
204     }
205     else if (service_type == SVC_SCRIPTED) {
206         // Script-controlled service
207         bool start_success = start_ps_process(std::vector<std::string>(1, "start"));
208         if (! start_success) {
209             failed_to_start();
210         }
211     }
212     else {
213         // "internal" service
214         started();
215     }
216 }
217
218 void ServiceRecord::started()
219 {
220     service_state = SVC_STARTED;
221     // TODO - inform listeners
222
223     if (desired_state == SVC_STARTED) {
224         // Start any dependents whose desired state is SVC_STARTED:
225         for (auto i = dependents.begin(); i != dependents.end(); i++) {
226             if ((*i)->desired_state == SVC_STARTED) {
227                 (*i)->start();
228             }
229         }
230         for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
231             if ((*i)->getFrom()->desired_state == SVC_STARTED) {
232                 (*i)->getFrom()->start();
233             }
234         }
235     }
236     else {
237         stop();
238     }
239 }
240
241 void ServiceRecord::failed_to_start()
242 {
243     service_state = SVC_STOPPED;
244     desired_state = SVC_STOPPED;
245     service_set->service_inactive(this);
246     // failure to start
247     // Cancel start of dependents:
248     for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
249         if ((*i)->desired_state == SVC_STARTED) {
250             (*i)->failed_dependency();
251         }
252     }    
253     for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
254         if ((*i)->getFrom()->desired_state == SVC_STARTED) {
255             // We can send 'start', because this is only a soft dependency.
256             // Our startup failure means that they don't have to wait for us.
257             (*i)->getFrom()->start();
258         }
259     }
260 }
261
262 bool ServiceRecord::start_ps_process()
263 {
264     return start_ps_process(std::vector<std::string>());
265 }
266
267
268 // TODO this can currently throw std::bad_alloc, fix that (in the worst case,
269 //      return failure instead).
270 bool ServiceRecord::start_ps_process(const std::vector<std::string> &pargs)
271 {
272     // In general, you can't tell whether fork/exec is successful. We use a pipe to communicate
273     // success/failure from the child to the parent. The pipe is set CLOEXEC so a successful
274     // exec closes the pipe, and the parent sees EOF. If the exec is unsuccessful, the errno
275     // is written to the pipe, and the parent can read it.
276
277     // TODO should NOT wait for the exec to succeed or fail here, as that could (when/if we allow
278     // running child processes with lower priority) result in priority inversion.
279
280     using std::vector;
281     using std::string;
282     
283     int pipefd[2];
284     if (pipe2(pipefd, O_CLOEXEC)) {
285         // TODO log error
286         return false;
287     }
288     
289     // TODO make sure pipefd's are not 0/1/2 (STDIN/OUT/ERR) - if they are, dup them
290     // until they are not.
291     
292     pid_t forkpid = fork();
293     if (forkpid == -1) {
294         // TODO log error
295         close(pipefd[0]);
296         close(pipefd[1]);
297         return false;
298     }
299     
300     if (forkpid == 0) {
301         // Child process
302         ev_default_destroy(); // won't need that on this side, free up fds.
303         
304         // Re-set stdin, stdout, stderr
305         close(0); close(1); close(2);
306         string logfile = this->logfile;
307         if (logfile.length() == 0) {
308             logfile = "/dev/null";
309         }
310         
311         // TODO rethink this logic. If we open it at not-0, shouldn't we just dup it to 0?:
312         if (open("/dev/null", O_RDONLY) == 0) {
313           // stdin = 0. That's what we should have; proceed with opening
314           // stdout and stderr.
315           open(logfile.c_str(), O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
316           dup2(1, 2);
317         }
318         
319         // Tokenize the command, and add additional arguments from pargs:
320         vector<string> progAndArgs = tokenize(program_name);
321         progAndArgs.insert(progAndArgs.end(), pargs.begin(), pargs.end());
322        
323         const char * pname = progAndArgs[0].c_str();
324         const char ** args = new const char *[progAndArgs.size() + 1];
325         
326         for (std::vector<std::string>::size_type i = 0; i < progAndArgs.size(); i++) {
327             args[i] = progAndArgs[i].c_str();
328         }
329         args[progAndArgs.size()] = nullptr;
330         
331         execvp(pname, const_cast<char **>(args));
332         
333         // If we got here, the exec failed:        
334         int exec_status = errno;
335         write(pipefd[1], &exec_status, sizeof(int));
336         exit(0);
337     }
338     else {
339         // Parent process
340         close(pipefd[1]); // close the 'other end' fd
341
342         int exec_status;        
343         if (read(pipefd[0], &exec_status, sizeof(int)) == 0) {
344             // pipe closed; success
345             pid = forkpid;
346
347             // Add a process listener so we can detect when the
348             // service stops
349             ev_child_init(&child_listener, process_child_callback, pid, 0);
350             child_listener.data = this;
351             ev_child_start(ev_default_loop(EVFLAG_AUTO), &child_listener);
352
353             close(pipefd[0]);
354             return true;
355         }
356         else {
357             // TODO log error
358             close(pipefd[0]);
359             return false;
360         }
361     }
362 }
363
364
365
366
367 // Mark this and all dependent services as force-stopped.
368 void ServiceRecord::forceStop()
369 {
370     force_stop = true;
371     stop();
372     for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
373         (*i)->forceStop();
374     }
375     // We don't want to force stop soft dependencies, however.
376 }
377
378 // A dependency of this service failed to start.
379 void ServiceRecord::failed_dependency()
380 {
381     desired_state = SVC_STOPPED;
382     
383     // Presumably, we were starting. So now we're not.
384     service_state = SVC_STOPPED;
385     
386     // Notify dependents of this service also
387     for (auto i = dependents.begin(); i != dependents.end(); i++) {
388         if ((*i)->desired_state == SVC_STARTED) {
389             (*i)->failed_dependency();
390         }
391     }
392     for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
393         if ((*i)->getFrom()->desired_state == SVC_STARTED) {
394             // It's a soft dependency, so send them 'started' rather than
395             // 'failed dep'.
396             (*i)->getFrom()->started();
397         }
398     }    
399 }
400
401 void ServiceRecord::dependentStopped()
402 {
403     if (service_state != SVC_STOPPED && (desired_state == SVC_STOPPED || force_stop)) {
404         // Check the other dependents before we stop.
405         if (stopCheckDependents()) {
406             stopping();
407         }
408     }
409 }
410
411 void ServiceRecord::stop()
412 {
413     if ((service_state == SVC_STOPPING || service_state == SVC_STOPPED)
414             && desired_state == SVC_STARTED) {
415         // The service *was* stopped/stopping, but it was going to restart.
416         // Now, we'll cancel the restart.
417         // TODO inform listeners waiting for start of cancellation
418     }
419     
420     if (desired_state == SVC_STOPPED) return;
421     
422     desired_state = SVC_STOPPED;
423
424     if (service_state != SVC_STARTED) {
425         if (service_state == SVC_STARTING) {
426             // Well this is awkward: we're going to have to continue
427             // starting, but we don't want any dependents to think that
428             // they are still waiting to start.
429             // Make sure they remain stopped:
430             stopDependents();
431         }
432         
433         // If we're starting we need to wait for that to complete.
434         // If we're already stopping/stopped there's nothing to do.
435         return;
436     }
437     
438     // If we get here, we are in STARTED state; stop all dependents.
439     if (stopCheckDependents()) {
440         stopping();
441     }
442 }
443
444 bool ServiceRecord::stopCheckDependents()
445 {
446     bool all_deps_stopped = true;
447     for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
448         if ((*i)->service_state != SVC_STOPPED) {
449             all_deps_stopped = false;
450             break;
451         }
452     }
453     
454     return all_deps_stopped;
455 }
456
457 bool ServiceRecord::stopDependents()
458 {
459     bool all_deps_stopped = true;
460     for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
461         if ((*i)->service_state != SVC_STOPPED) {
462             all_deps_stopped = false;
463             (*i)->stop();
464         }
465     }
466     
467     return all_deps_stopped;
468 }
469
470
471
472 // Dependency stopped or is stopping; we must stop too.
473 void ServiceRecord::stopping()
474 {
475     service_state = SVC_STOPPING;
476
477     if (service_type == SVC_PROCESS) {
478         if (pid != -1) {
479           // The process is still kicking on - must actually kill it.
480           kill(pid, SIGTERM);
481           // Now we wait; the rest is done in process_child_callback
482         }
483         else {
484             // The process is already dead.
485             stopped();
486         }
487     }
488     else {
489         // Scripted service.
490         start_ps_process(std::vector<string>(1, "stop"));
491     }    
492 }
493
494 void ServiceSet::service_active(ServiceRecord *sr)
495 {
496     active_services++;
497 }
498
499 void ServiceSet::service_inactive(ServiceRecord *sr)
500 {
501     active_services--;
502 }