s->pid_file_pathspec = mfree(s->pid_file_pathspec);
}
-static int service_set_main_pid(Service *s, pid_t pid) {
- _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
- int r;
-
+static int service_set_main_pidref(Service *s, PidRef *pidref) {
assert(s);
- if (pid <= 1)
+ /* Takes ownership of the specified pidref on success, but not on failure. */
+
+ if (!pidref_is_set(pidref))
+ return -ESRCH;
+
+ if (pidref->pid <= 1)
return -EINVAL;
- if (pid == getpid_cached())
+ if (pidref->pid == getpid_cached())
return -EINVAL;
- if (s->main_pid.pid == pid && s->main_pid_known)
+ if (s->main_pid.pid == pidref->pid && s->main_pid_known) {
+ pidref_done(pidref);
return 0;
+ }
- r = pidref_set_pid(&pidref, pid);
- if (r < 0)
- return r;
-
- if (s->main_pid.pid != pid) {
+ if (s->main_pid.pid != pidref->pid) {
service_unwatch_main_pid(s);
- exec_status_start(&s->main_exec_status, pid);
+ exec_status_start(&s->main_exec_status, pidref->pid);
}
- s->main_pid = TAKE_PIDREF(pidref);
+ s->main_pid = TAKE_PIDREF(*pidref);
s->main_pid_known = true;
- s->main_pid_alien = pid_is_my_child(pid) == 0;
+ s->main_pid_alien = pid_is_my_child(s->main_pid.pid) == 0;
if (s->main_pid_alien)
- log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid);
+ log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", s->main_pid.pid);
return 0;
}
+static int service_set_main_pid(Service *s, pid_t pid) {
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ int r;
+
+ assert(s);
+
+ r = pidref_set_pid(&pidref, pid);
+ if (r < 0)
+ return r;
+
+ return service_set_main_pidref(s, &pidref);
+}
+
void service_release_socket_fd(Service *s) {
assert(s);
}
static int service_load_pid_file(Service *s, bool may_warn) {
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
bool questionable_pid_file = false;
_cleanup_free_ char *k = NULL;
_cleanup_close_ int fd = -EBADF;
if (s->main_pid_known && pid == s->main_pid.pid)
return 0;
- r = service_is_suitable_main_pid(s, pid, prio);
+ r = pidref_set_pid(&pidref, pid);
+ if (r < 0)
+ return log_unit_full_errno(UNIT(s), prio, r, "Failed to pin PID " PID_FMT ": %m", pid);
+
+ r = service_is_suitable_main_pid(s, pidref.pid, prio);
if (r < 0)
return r;
if (r == 0) {
if (st.st_uid != 0)
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EPERM),
- "New main PID "PID_FMT" does not belong to service, and PID file is not owned by root. Refusing.", pid);
+ "New main PID "PID_FMT" does not belong to service, and PID file is not owned by root. Refusing.", pidref.pid);
- log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, but we'll accept it since PID file is owned by root.", pid);
+ log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, but we'll accept it since PID file is owned by root.", pidref.pid);
}
if (s->main_pid_known) {
- log_unit_debug(UNIT(s), "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid.pid, pid);
+ log_unit_debug(UNIT(s), "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid.pid, pidref.pid);
service_unwatch_main_pid(s);
s->main_pid_known = false;
} else
- log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pid);
+ log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pidref.pid);
- r = service_set_main_pid(s, pid);
+ r = service_set_main_pidref(s, &pidref);
if (r < 0)
return r;
- r = unit_watch_pid(UNIT(s), pid, /* exclusive= */ false);
+ r = unit_watch_pid(UNIT(s), s->main_pid.pid, /* exclusive= */ false);
if (r < 0) /* FIXME: we need to do something here */
- return log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", pid);
+ return log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", s->main_pid.pid);
return 1;
}
if (service_set_main_pid(s, pid) < 0)
return;
- r = unit_watch_pid(UNIT(s), pid, /* exclusive= */ false);
+ r = unit_watch_pid(UNIT(s), s->main_pid.pid, /* exclusive= */ false);
if (r < 0)
/* FIXME: we need to do something here */
- log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", pid);
+ log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", s->main_pid.pid);
}
static void service_set_state(Service *s, ServiceState state) {
/* For simple services we immediately start
* the START_POST binaries. */
- (void) service_set_main_pid(s, pidref.pid);
+ (void) service_set_main_pidref(s, &pidref);
service_enter_start_post(s);
} else if (s->type == SERVICE_FORKING) {
/* For D-Bus services we know the main pid right away, but wait for the bus name to appear on the
* bus. 'notify' and 'exec' services are similar. */
- (void) service_set_main_pid(s, pidref.pid);
+ (void) service_set_main_pidref(s, &pidref);
service_set_state(s, SERVICE_START);
} else
assert_not_reached();
if (r < 0)
goto fail;
- (void) service_set_main_pid(s, pidref.pid);
-
+ (void) service_set_main_pidref(s, &pidref);
return;
fail: