service: Don't stop unneeded units needed by restarted service (#7526)

An auto-restarted unit B may depend on unit A with StopWhenUnneeded=yes.
If A stops before B's restart timeout expires, it'll be started again as part
of B's dependent jobs. However, if stopping takes longer than the timeout, B's
running stop job collides start job which also cancels B's start job. Result is
that neither A or B are active.

Currently, when a service with automatic restarting fails, it transitions
through following states:
        1) SERVICE_FAILED or SERVICE_DEAD to indicate the failure,
        2) SERVICE_AUTO_RESTART while restart timer is running.

The StopWhenUnneeded= check takes place in service_enter_dead between the two
state mentioned above. We temporarily store the auto restart flag to query it
during the check. Because we don't return control to the main event loop, this
new service unit flag needn't be serialized.

This patch prevents the pathologic situation when the service with Restart=
won't restart automatically. As a side effect it also avoid restarting the
dependency unit with StopWhenUnneeded=yes.

Fixes: #7377
This commit is contained in:
Michal Koutný
2017-12-05 16:51:19 +01:00
committed by Lennart Poettering
parent 0eb89fe6b6
commit deb4e7080d
4 changed files with 29 additions and 4 deletions
+4
View File
@@ -484,6 +484,9 @@ struct UnitVTable {
* unit is in. */
const char* (*sub_state_to_string)(Unit *u);
/* Additionally to UnitActiveState determine whether unit is to be restarted. */
bool (*will_restart)(Unit *u);
/* Return true when there is reason to keep this entry around
* even nothing references it and it isn't active in any
* way */
@@ -706,6 +709,7 @@ const char *unit_slice_name(Unit *u);
bool unit_stop_pending(Unit *u) _pure_;
bool unit_inactive_or_pending(Unit *u) _pure_;
bool unit_active_or_pending(Unit *u);
bool unit_will_restart(Unit *u);
int unit_add_default_target_dependency(Unit *u, Unit *target);