SOCKET_CLEANING);
}
+static bool SOCKET_SERVICE_IS_ACTIVE(Service *s, bool allow_finalize) {
+ assert(s);
+
+ /* If unit_active_state() reports inactive/failed then it's all good, otherwise we need to
+ * manually exclude SERVICE_AUTO_RESTART and SERVICE_AUTO_RESTART_QUEUED, in which cases
+ * the start job hasn't been enqueued/run, but are only placeholders in order to allow
+ * canceling auto restart. */
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(UNIT(s))))
+ return false;
+
+ if (IN_SET(s->state, SERVICE_AUTO_RESTART, SERVICE_AUTO_RESTART_QUEUED))
+ return false;
+
+ if (allow_finalize && IN_SET(s->state, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, SERVICE_CLEANING))
+ return false;
+
+ return true;
+}
+
static void socket_init(Unit *u) {
Socket *s = SOCKET(u);
/* Cannot run this without the service being around */
if (UNIT_ISSET(s->service)) {
- Service *service;
-
- service = SERVICE(UNIT_DEREF(s->service));
+ Service *service = ASSERT_PTR(SERVICE(UNIT_DEREF(s->service)));
if (UNIT(service)->load_state != UNIT_LOADED)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOENT),
"Socket service %s not loaded, refusing.", UNIT(service)->id);
- /* If the service is already active we cannot start the
- * socket */
- if (!IN_SET(service->state,
- SERVICE_DEAD, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_DEAD_RESOURCES_PINNED, SERVICE_FAILED, SERVICE_FAILED_BEFORE_AUTO_RESTART,
- SERVICE_AUTO_RESTART, SERVICE_AUTO_RESTART_QUEUED))
+ /* If the service is already active we cannot start the socket */
+ if (SOCKET_SERVICE_IS_ACTIVE(service, /* allow_finalize = */ false))
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EBUSY),
"Socket service %s already active, refusing.", UNIT(service)->id);
}
/* Filter out invocations with bogus state */
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
- assert(other->type == UNIT_SERVICE);
+
+ Service *service = ASSERT_PTR(SERVICE(other));
/* Don't propagate state changes from the service if we are already down */
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))
if (other->job)
return;
- if (IN_SET(SERVICE(other)->state,
- SERVICE_DEAD, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_DEAD_RESOURCES_PINNED, SERVICE_FAILED, SERVICE_FAILED_BEFORE_AUTO_RESTART,
- SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
- SERVICE_AUTO_RESTART, SERVICE_AUTO_RESTART_QUEUED))
- socket_enter_listening(s);
+ if (!SOCKET_SERVICE_IS_ACTIVE(service, /* allow_finalize = */ true))
+ socket_enter_listening(s);
if (SERVICE(other)->state == SERVICE_RUNNING)
socket_set_state(s, SOCKET_RUNNING);