[SERVICE_STOP_POST] = UNIT_DEACTIVATING,
[SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
[SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_MAINTAINANCE] = UNIT_INACTIVE,
+ [SERVICE_MAINTENANCE] = UNIT_INACTIVE,
[SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
};
free(s->sysv_runlevels);
s->sysv_runlevels = NULL;
+ free(s->status_text);
+ s->status_text = NULL;
+
exec_context_done(&s->exec_context);
exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
s->control_command = NULL;
fprintf(f, "%sSysVRunLevels: %s\n",
prefix, s->sysv_runlevels);
+ if (s->status_text)
+ fprintf(f, "%sStatus Text: %s\n",
+ prefix, s->status_text);
+
free(p2);
}
if ((unsigned long) (pid_t) p != p)
return -ERANGE;
+ if (p <= 1)
+ return -ERANGE;
+
if (kill((pid_t) p, 0) < 0 && errno != EPERM) {
log_warning("PID %llu read from file %s does not exist. Your service or init script might be broken.",
(unsigned long long) p, s->pid_file);
state == SERVICE_STOP_POST ||
state == SERVICE_FINAL_SIGTERM ||
state == SERVICE_FINAL_SIGKILL ||
- state == SERVICE_MAINTAINANCE ||
+ state == SERVICE_MAINTENANCE ||
state == SERVICE_AUTO_RESTART)
service_notify_sockets_dead(s);
if ((s->deserialized_state == SERVICE_START &&
(s->type == SERVICE_FORKING ||
- s->type == SERVICE_DBUS)) ||
+ s->type == SERVICE_DBUS ||
+ s->type == SERVICE_FINISH ||
+ s->type == SERVICE_NOTIFY)) ||
s->deserialized_state == SERVICE_START_POST ||
s->deserialized_state == SERVICE_RUNNING ||
s->deserialized_state == SERVICE_RELOAD ||
service_set_state(s, SERVICE_AUTO_RESTART);
} else
- service_set_state(s, s->failure ? SERVICE_MAINTAINANCE : SERVICE_DEAD);
+ service_set_state(s, s->failure ? SERVICE_MAINTENANCE : SERVICE_DEAD);
return;
if ((r = service_spawn(s,
s->exec_command[SERVICE_EXEC_START],
- s->type == SERVICE_FORKING || s->type == SERVICE_DBUS,
+ s->type == SERVICE_FORKING || s->type == SERVICE_DBUS || s->type == SERVICE_NOTIFY,
true,
true,
true,
service_set_state(s, SERVICE_START);
} else if (s->type == SERVICE_FINISH ||
- s->type == SERVICE_DBUS) {
+ s->type == SERVICE_DBUS ||
+ s->type == SERVICE_NOTIFY) {
/* For finishing services we wait until the start
* process exited, too, but it is our main process. */
/* For D-Bus services we know the main pid right away,
- * but wait for the bus name to appear on the bus. */
+ * but wait for the bus name to appear on the
+ * bus. Notify services are similar. */
s->main_pid = pid;
s->main_pid_known = true;
s->state == SERVICE_START_POST)
return 0;
- assert(s->state == SERVICE_DEAD || s->state == SERVICE_MAINTAINANCE || s->state == SERVICE_AUTO_RESTART);
+ assert(s->state == SERVICE_DEAD || s->state == SERVICE_MAINTENANCE || s->state == SERVICE_AUTO_RESTART);
/* Make sure we don't enter a busy loop of some kind. */
if (!ratelimit_test(&s->ratelimit)) {
exec_status_fill(&s->main_exec_status, pid, code, status);
s->main_pid = 0;
- if (s->type == SERVICE_SIMPLE || s->type == SERVICE_FINISH) {
+ if (s->type != SERVICE_FORKING) {
assert(s->exec_command[SERVICE_EXEC_START]);
s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status;
}
service_enter_signal(s, SERVICE_FINAL_SIGTERM, false);
break;
} else {
- assert(s->type == SERVICE_DBUS);
+ assert(s->type == SERVICE_DBUS || s->type == SERVICE_NOTIFY);
/* Fall through */
}
assert_not_reached("Uh, control process died at wrong time.");
}
}
- } else
- assert_not_reached("Got SIGCHLD for unkown PID");
+ }
}
static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
break;
case SERVICE_FINAL_SIGKILL:
- log_warning("%s still around after SIGKILL (2). Entering maintainance mode.", u->meta.id);
+ log_warning("%s still around after SIGKILL (2). Entering maintenance mode.", u->meta.id);
service_enter_dead(s, false, true);
break;
}
}
+static void service_notify_message(Unit *u, char **tags) {
+ Service *s = SERVICE(u);
+ const char *e;
+
+ assert(u);
+
+ log_debug("%s: Got message", u->meta.id);
+
+ /* Interpret MAINPID= */
+ if ((e = strv_find_prefix(tags, "MAINPID=")) &&
+ (s->state == SERVICE_START ||
+ s->state == SERVICE_START_POST ||
+ s->state == SERVICE_RUNNING ||
+ s->state == SERVICE_RELOAD)) {
+ unsigned long pid;
+
+ if (safe_atolu(e + 8, &pid) < 0 ||
+ (unsigned long) (pid_t) pid != pid ||
+ pid <= 1)
+ log_warning("Failed to parse %s", e);
+ else {
+ log_debug("%s: got %s", u->meta.id, e);
+ s->main_pid = (pid_t) pid;
+ }
+ }
+
+ /* Interpret READY= */
+ if (s->type == SERVICE_NOTIFY &&
+ s->state == SERVICE_START &&
+ strv_find(tags, "READY=1")) {
+ log_debug("%s: got READY=1", u->meta.id);
+
+ service_enter_start_post(s);
+ }
+
+ /* Interpret STATUS= */
+ if ((e = strv_find_prefix(tags, "STATUS="))) {
+ char *t;
+
+ if (!(t = strdup(e+7))) {
+ log_error("Failed to allocate string.");
+ return;
+ }
+
+ log_debug("%s: got %s", u->meta.id, e);
+
+ free(s->status_text);
+ s->status_text = t;
+ }
+}
+
static int service_enumerate(Manager *m) {
char **p;
unsigned i;
[SERVICE_STOP_POST] = "stop-post",
[SERVICE_FINAL_SIGTERM] = "final-sigterm",
[SERVICE_FINAL_SIGKILL] = "final-sigkill",
- [SERVICE_MAINTAINANCE] = "maintainance",
+ [SERVICE_MAINTENANCE] = "maintenance",
[SERVICE_AUTO_RESTART] = "auto-restart",
};
[SERVICE_FORKING] = "forking",
[SERVICE_SIMPLE] = "simple",
[SERVICE_FINISH] = "finish",
- [SERVICE_DBUS] = "dbus"
+ [SERVICE_DBUS] = "dbus",
+ [SERVICE_NOTIFY] = "notify"
};
DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
.timer_event = service_timer_event,
.cgroup_notify_empty = service_cgroup_notify_event,
+ .notify_message = service_notify_message,
.bus_name_owner_change = service_bus_name_owner_change,
.bus_query_pid_done = service_bus_query_pid_done,