sent along with the specified signal, unless the \fBnosigterm\fR option is
specified via the \fBoptions\fR parameter.
.TP
+\fBready-notification\fR = {\fBpipefd:\fR\fIfd-number\fR | \fBpipevar:\fR\fIenv-var-name\fR}
+Specifies the mechanism, if any, by which a process service will notify that it is ready
+(successfully started). If not specified, a process service is considered started as soon as it
+has begun execution. The two options are:
+.RS
+.IP \(bu
+\fBpipefd:\fR\fIfd-number\fR \(em the service will write a message to the specified file descriptor,
+which \fBdinit\fR sets up as the write end of a pipe before execution. This mechanism is compatible
+with the S6 supervision suite.
+.IP \(bu
+\fBpipevar:\fR\fIenv-var-name\fR \(em the service will write a message to file descriptor identified
+using the contents of the specified environment variable, which will be set by \fBdinit\fR before
+execution to a file descriptor (chosen arbitrarily) attached to the write end of a pipe.
+.RE
+.TP
\fBlogfile\fR = \fIlog-file-path\fR
Specifies the log file for the service. Output from the service process
will go this file.
}
}
+// Check if one string starts with another
+static bool starts_with(string s, const char *prefix)
+{
+ const char * sp = s.c_str();
+ while (*sp != 0 && *prefix != 0) {
+ if (*sp != *prefix) return false;
+ sp++; prefix++;
+ }
+ return *prefix == 0;
+}
+
// Find a service record, or load it from file. If the service has
// dependencies, load those also.
//
timespec stop_timeout = { .tv_sec = 10, .tv_nsec = 0 };
timespec start_timeout = { .tv_sec = 60, .tv_nsec = 0 };
+ int readiness_fd = -1; // readiness fd in service process
+ std::string readiness_var; // environment var to hold readiness fd
+
uid_t run_as_uid = -1;
gid_t run_as_gid = -1;
else if (setting == "chain-to") {
chain_to_name = read_setting_value(i, end, nullptr);
}
+ else if (setting == "ready-notification") {
+ string notify_setting = read_setting_value(i, end, nullptr);
+ if (starts_with(notify_setting, "pipefd:")) {
+ readiness_fd = parse_unum_param(notify_setting.substr(7 /* len 'pipefd:' */),
+ name, std::numeric_limits<int>::max());
+ }
+ else if (starts_with(notify_setting, "pipevar:")) {
+ readiness_var = notify_setting.substr(8 /* len 'pipevar:' */);
+ if (readiness_var.empty()) {
+ throw service_description_exc(name, "Invalid pipevar variable name "
+ "in ready-notification");
+ }
+ }
+ else {
+ throw service_description_exc(name, "Unknown ready-notification setting: "
+ + notify_setting);
+ }
+ }
else {
throw service_description_exc(name, "Unknown setting: " + setting);
}
rvalps->set_extra_termination_signal(term_signal);
rvalps->set_run_as_uid_gid(run_as_uid, run_as_gid);
rvalps->set_workding_dir(working_dir);
+ rvalps->set_notification_fd(readiness_fd);
+ rvalps->set_notification_var(std::move(readiness_var));
// process service start / run on console must be the same:
onstart_flags.starts_on_console = onstart_flags.runs_on_console;
rval = rvalps;