13 // Find the requested service by name
14 static ServiceRecord * findService(const std::list<ServiceRecord *> & records,
18 list<ServiceRecord *>::const_iterator i = records.begin();
19 for ( ; i != records.end(); i++ ) {
20 if (strcmp((*i)->getServiceName(), name) == 0) {
24 return (ServiceRecord *)0;
27 ServiceRecord * ServiceSet::findService(std::string name)
29 return ::findService(records, name.c_str());
32 void ServiceSet::startService(const char *name)
35 ServiceRecord *record = loadServiceRecord(name);
40 void ServiceSet::stopService(const std::string & name)
42 ServiceRecord *record = findService(name);
43 if (record != nullptr) {
48 // Called when a service has actually stopped.
49 void ServiceRecord::stopped()
51 service_state = ServiceState::STOPPED;
54 // Stop any dependencies whose desired state is STOPPED:
55 for (sr_iter i = depends_on.begin(); i != depends_on.end(); i++) {
56 (*i)->dependentStopped();
59 service_set->service_inactive(this);
61 // TODO inform listeners.
62 if (desired_state == ServiceState::STARTED) {
63 // Desired state is "started".
68 void ServiceRecord::process_child_callback(struct ev_loop *loop, ev_child *w, int revents)
70 ServiceRecord *sr = (ServiceRecord *) w->data;
73 ev_child_stop(ev_default_loop(EVFLAG_AUTO), &sr->child_listener);
75 // Ok, for a process service, any process death which we didn't rig
76 // ourselves is a bit... unexpected. Probably, the child died because
77 // we asked it to (sr->service_state == STOPPING). But even if
78 // we didn't, there's not much we can do.
80 if (sr->service_type == ServiceType::PROCESS) {
81 // TODO log non-zero rstatus?
82 if (sr->service_state == ServiceState::STOPPING) {
89 if (sr->auto_restart && sr->service_set->get_auto_restart()) {
94 if (sr->service_state == ServiceState::STOPPING) {
95 if (w->rstatus == 0) {
100 // ??? failed to stop!
101 // For now just pretend we stopped, so that any dependencies
107 if (w->rstatus == 0) {
112 sr->failed_to_start();
118 void ServiceRecord::start()
120 if ((service_state == ServiceState::STARTING || service_state == ServiceState::STARTED)
121 && desired_state == ServiceState::STOPPED) {
122 // This service was starting, or started, but was set to be stopped.
123 // Cancel the stop (and continue starting/running).
124 // TODO any listeners waiting for stop should be notified of
128 auto old_desired_state = desired_state;
129 desired_state = ServiceState::STARTED;
131 if (service_state == ServiceState::STARTED || service_state == ServiceState::STARTING) {
132 // We couldn't be started or starting unless all dependencies have
133 // already started: so there's nothing left to do.
137 bool all_deps_started = true;
139 // Ask dependencies to start, mark them as being waited on.
141 for (sr_iter i = depends_on.begin(); i != depends_on.end(); ++i) {
142 // Note, we cannot treat a dependency as started if its force_stop
144 if ((*i)->service_state != ServiceState::STARTED || (*i)->force_stop) {
145 all_deps_started = false;
150 if (old_desired_state != ServiceState::STARTED) {
151 // This is a fresh start, so we mark all soft dependencies as 'waiting on' and ask them
153 for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
154 if (i->getTo()->service_state != ServiceState::STARTED) {
155 all_deps_started = false;
157 i->waiting_on = true;
162 // This is (or at least may be) a notification that a dependency is ready; let's
164 for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
165 ServiceRecord * to = i->getTo();
167 if ((to->desired_state != ServiceState::STARTED && to->service_state != ServiceState::STARTING) || to->service_state == ServiceState::STARTED) {
168 // Service has either started or is no longer starting
169 i->waiting_on = false;
172 all_deps_started = false;
178 if (! all_deps_started) {
179 // The dependencies will notify this service once they've started.
183 // Actually start this service.
184 service_state = ServiceState::STARTING;
185 service_set->service_active(this);
187 if (service_type == ServiceType::PROCESS) {
188 bool start_success = start_ps_process();
196 else if (service_type == ServiceType::SCRIPTED) {
197 // Script-controlled service
198 bool start_success = start_ps_process(std::vector<std::string>(1, "start"));
199 if (! start_success) {
204 // "internal" service
209 void ServiceRecord::started()
211 service_state = ServiceState::STARTED;
212 // TODO - inform listeners
214 if (desired_state == ServiceState::STARTED) {
215 // Start any dependents whose desired state is STARTED:
216 for (auto i = dependents.begin(); i != dependents.end(); i++) {
217 if ((*i)->desired_state == ServiceState::STARTED) {
221 for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
222 if ((*i)->getFrom()->desired_state == ServiceState::STARTED) {
223 (*i)->getFrom()->start();
232 void ServiceRecord::failed_to_start()
234 service_state = ServiceState::STOPPED;
235 desired_state = ServiceState::STOPPED;
236 service_set->service_inactive(this);
238 // Cancel start of dependents:
239 for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
240 if ((*i)->desired_state == ServiceState::STARTED) {
241 (*i)->failed_dependency();
244 for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
245 if ((*i)->getFrom()->desired_state == ServiceState::STARTED) {
246 // We can send 'start', because this is only a soft dependency.
247 // Our startup failure means that they don't have to wait for us.
248 (*i)->getFrom()->start();
253 bool ServiceRecord::start_ps_process() noexcept
256 return start_ps_process(std::vector<std::string>());
258 catch (std::bad_alloc & bad_alloc_exc) {
264 // TODO this can currently throw std::bad_alloc, fix that (in the worst case,
265 // return failure instead).
266 bool ServiceRecord::start_ps_process(const std::vector<std::string> &pargs) noexcept
268 // In general, you can't tell whether fork/exec is successful. We use a pipe to communicate
269 // success/failure from the child to the parent. The pipe is set CLOEXEC so a successful
270 // exec closes the pipe, and the parent sees EOF. If the exec is unsuccessful, the errno
271 // is written to the pipe, and the parent can read it.
273 // TODO should NOT wait for the exec to succeed or fail here, as that could (when/if we allow
274 // running child processes with lower priority) result in priority inversion.
280 if (pipe2(pipefd, O_CLOEXEC)) {
285 // Set up the argument array and other data now (before fork), in case memory allocation fails.
288 //auto argsv = std::vector<const char *>(num_args + pargs.size() + 1);
289 auto argsv = std::vector<const char *>(num_args + pargs.size() + 1);
290 auto args = argsv.data();
292 for (i = 0; i < num_args; i++) {
293 args[i] = exec_arg_parts[i];
295 for (auto progarg : pargs) {
296 args[i] = progarg.c_str();
301 string logfile = this->logfile;
302 if (logfile.length() == 0) {
303 logfile = "/dev/null";
306 // TODO make sure pipefd's are not 0/1/2 (STDIN/OUT/ERR) - if they are, dup them
307 // until they are not.
309 pid_t forkpid = fork();
318 // Child process. Must not allocate memory (or otherwise risk throwing any exception)
319 // from here until exit().
320 ev_default_destroy(); // won't need that on this side, free up fds.
322 // Re-set stdin, stdout, stderr
323 close(0); close(1); close(2);
325 // TODO rethink this logic. If we open it at not-0, shouldn't we just dup it to 0?:
326 if (open("/dev/null", O_RDONLY) == 0) {
327 // stdin = 0. That's what we should have; proceed with opening
328 // stdout and stderr.
329 open(logfile.c_str(), O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
333 execvp(exec_arg_parts[0], const_cast<char **>(args));
335 // If we got here, the exec failed:
336 int exec_status = errno;
337 write(pipefd[1], &exec_status, sizeof(int));
342 close(pipefd[1]); // close the 'other end' fd
345 if (read(pipefd[0], &exec_status, sizeof(int)) == 0) {
346 // pipe closed; success
349 // Add a process listener so we can detect when the
351 ev_child_init(&child_listener, process_child_callback, pid, 0);
352 child_listener.data = this;
353 ev_child_start(ev_default_loop(EVFLAG_AUTO), &child_listener);
365 catch (std::bad_alloc &bad_alloc_exc) {
374 // Mark this and all dependent services as force-stopped.
375 void ServiceRecord::forceStop()
379 for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
382 // We don't want to force stop soft dependencies, however.
385 // A dependency of this service failed to start.
386 void ServiceRecord::failed_dependency()
388 desired_state = ServiceState::STOPPED;
390 // Presumably, we were starting. So now we're not.
391 service_state = ServiceState::STOPPED;
393 // Notify dependents of this service also
394 for (auto i = dependents.begin(); i != dependents.end(); i++) {
395 if ((*i)->desired_state == ServiceState::STARTED) {
396 (*i)->failed_dependency();
399 for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
400 if ((*i)->getFrom()->desired_state == ServiceState::STARTED) {
401 // It's a soft dependency, so send them 'started' rather than
403 (*i)->getFrom()->started();
408 void ServiceRecord::dependentStopped()
410 if (service_state != ServiceState::STOPPED && (desired_state == ServiceState::STOPPED || force_stop)) {
411 // Check the other dependents before we stop.
412 if (stopCheckDependents()) {
418 void ServiceRecord::stop()
420 if ((service_state == ServiceState::STOPPING || service_state == ServiceState::STOPPED)
421 && desired_state == ServiceState::STARTED) {
422 // The service *was* stopped/stopping, but it was going to restart.
423 // Now, we'll cancel the restart.
424 // TODO inform listeners waiting for start of cancellation
427 if (desired_state == ServiceState::STOPPED) return;
429 desired_state = ServiceState::STOPPED;
431 if (service_state != ServiceState::STARTED) {
432 if (service_state == ServiceState::STARTING) {
433 // Well this is awkward: we're going to have to continue
434 // starting, but we don't want any dependents to think that
435 // they are still waiting to start.
436 // Make sure they remain stopped:
440 // If we're starting we need to wait for that to complete.
441 // If we're already stopping/stopped there's nothing to do.
445 // If we get here, we are in STARTED state; stop all dependents.
446 if (stopCheckDependents()) {
451 bool ServiceRecord::stopCheckDependents()
453 bool all_deps_stopped = true;
454 for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
455 if ((*i)->service_state != ServiceState::STOPPED) {
456 all_deps_stopped = false;
461 return all_deps_stopped;
464 bool ServiceRecord::stopDependents()
466 bool all_deps_stopped = true;
467 for (sr_iter i = dependents.begin(); i != dependents.end(); ++i) {
468 if ((*i)->service_state != ServiceState::STOPPED) {
469 all_deps_stopped = false;
474 return all_deps_stopped;
479 // Dependency stopped or is stopping; we must stop too.
480 void ServiceRecord::stopping()
482 service_state = ServiceState::STOPPING;
484 if (service_type == ServiceType::PROCESS) {
486 // The process is still kicking on - must actually kill it.
488 // Now we wait; the rest is done in process_child_callback
491 // The process is already dead.
497 start_ps_process(std::vector<string>(1, "stop"));
501 void ServiceSet::service_active(ServiceRecord *sr)
506 void ServiceSet::service_inactive(ServiceRecord *sr)