12 // Find the requested service by name
13 static ServiceRecord * findService(const std::list<ServiceRecord *> & records,
17 list<ServiceRecord *>::const_iterator i = records.begin();
18 for ( ; i != records.end(); i++ ) {
19 if (strcmp((*i)->getServiceName(), name) == 0) {
23 return (ServiceRecord *)0;
26 ServiceRecord * ServiceSet::findService(std::string name)
28 return ::findService(records, name.c_str());
31 void ServiceSet::startService(const char *name)
34 ServiceRecord *record = loadServiceRecord(name);
39 void ServiceSet::stopService(const std::string & name)
41 ServiceRecord *record = findService(name);
42 if (record != nullptr) {
47 // Called when a service has actually stopped.
48 void ServiceRecord::stopped()
50 service_state = SVC_STOPPED;
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();
58 service_set->service_inactive(this);
60 // TODO inform listeners.
61 if (desired_state == SVC_STARTED) {
62 // Desired state is "started".
67 void ServiceRecord::process_child_callback(struct ev_loop *loop, ev_child *w, int revents)
69 ServiceRecord *sr = (ServiceRecord *) w->data;
72 ev_child_stop(ev_default_loop(EVFLAG_AUTO), &sr->child_listener);
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.
79 if (sr->service_type == SVC_PROCESS) {
80 // TODO log non-zero rstatus?
81 if (sr->service_state == SVC_STOPPING) {
88 if (sr->auto_restart && sr->service_set->get_auto_restart()) {
92 else { // SVC_SCRIPTED
93 if (sr->service_state == SVC_STOPPING) {
94 if (w->rstatus == 0) {
99 // ??? failed to stop!
100 // For now just pretend we stopped, so that any dependencies
105 else { // SVC_STARTING
106 if (w->rstatus == 0) {
111 sr->failed_to_start();
117 void ServiceRecord::start()
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
127 auto old_desired_state = desired_state;
128 desired_state = SVC_STARTED;
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.
136 bool all_deps_started = true;
138 // Ask dependencies to start, mark them as being waited on.
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
143 if ((*i)->service_state != SVC_STARTED || (*i)->force_stop) {
144 all_deps_started = false;
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
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;
156 i->waiting_on = true;
161 // This is (or at least may be) a notification that a dependency is ready; let's
163 for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
164 ServiceRecord * to = i->getTo();
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;
171 all_deps_started = false;
177 if (! all_deps_started) {
178 // The dependencies will notify this service once they've started.
182 // Actually start this service.
183 service_state = SVC_STARTING;
184 service_set->service_active(this);
186 if (service_type == SVC_PROCESS) {
187 bool start_success = start_ps_process();
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) {
203 // "internal" service
208 void ServiceRecord::started()
210 service_state = SVC_STARTED;
211 // TODO - inform listeners
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) {
220 for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
221 if ((*i)->getFrom()->desired_state == SVC_STARTED) {
222 (*i)->getFrom()->start();
231 void ServiceRecord::failed_to_start()
233 service_state = SVC_STOPPED;
234 desired_state = SVC_STOPPED;
235 service_set->service_inactive(this);
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();
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();
252 bool ServiceRecord::start_ps_process()
254 return start_ps_process(std::vector<std::string>());
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)
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.
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.
274 if (pipe2(pipefd, O_CLOEXEC)) {
279 // TODO make sure pipefd's are not 0/1/2 (STDIN/OUT/ERR) - if they are, dup them
280 // until they are not.
282 pid_t forkpid = fork();
292 ev_default_destroy(); // won't need that on this side, free up fds.
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";
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);
309 const char ** args = new const char *[num_args + pargs.size() + 1];
311 for (i = 0; i < num_args; i++) {
312 args[i] = exec_arg_parts[i];
314 for (auto progarg : pargs) {
315 args[i] = progarg.c_str();
320 execvp(exec_arg_parts[0], const_cast<char **>(args));
322 // If we got here, the exec failed:
323 int exec_status = errno;
324 write(pipefd[1], &exec_status, sizeof(int));
329 close(pipefd[1]); // close the 'other end' fd
332 if (read(pipefd[0], &exec_status, sizeof(int)) == 0) {
333 // pipe closed; success
336 // Add a process listener so we can detect when the
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);
356 // Mark this and all dependent services as force-stopped.
357 void ServiceRecord::forceStop()
361 for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
364 // We don't want to force stop soft dependencies, however.
367 // A dependency of this service failed to start.
368 void ServiceRecord::failed_dependency()
370 desired_state = SVC_STOPPED;
372 // Presumably, we were starting. So now we're not.
373 service_state = SVC_STOPPED;
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();
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
385 (*i)->getFrom()->started();
390 void ServiceRecord::dependentStopped()
392 if (service_state != SVC_STOPPED && (desired_state == SVC_STOPPED || force_stop)) {
393 // Check the other dependents before we stop.
394 if (stopCheckDependents()) {
400 void ServiceRecord::stop()
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
409 if (desired_state == SVC_STOPPED) return;
411 desired_state = SVC_STOPPED;
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:
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.
427 // If we get here, we are in STARTED state; stop all dependents.
428 if (stopCheckDependents()) {
433 bool ServiceRecord::stopCheckDependents()
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;
443 return all_deps_stopped;
446 bool ServiceRecord::stopDependents()
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;
456 return all_deps_stopped;
461 // Dependency stopped or is stopping; we must stop too.
462 void ServiceRecord::stopping()
464 service_state = SVC_STOPPING;
466 if (service_type == SVC_PROCESS) {
468 // The process is still kicking on - must actually kill it.
470 // Now we wait; the rest is done in process_child_callback
473 // The process is already dead.
479 start_ps_process(std::vector<string>(1, "stop"));
483 void ServiceSet::service_active(ServiceRecord *sr)
488 void ServiceSet::service_inactive(ServiceRecord *sr)