Is it possible to make a systemd unit wait until all its Conflicts= are stopped before trying to start

systemd

I have a series of mutually exclusive systemd services that are started and stopped by users as needed. Each of the services requires exclusive use of some hardware, so many of the services conflict with each other. (But not all services conflict with all other services)

To manage this I've used Conflicts=, which almost works perfectly, however the ExecStart of the starting service seems to run while the ExecStop script of the conflicting service is still running running, which causes the starting service to fail as the hardware resources are not yet available.

If I have the start scripts sleep for some safe amount of time, like 30 seconds, they function perfectly, but I'd much rather them start as soon as the conflicting service stops.

After= doesn't seem to work as the services can be stopped and started repeatedly, in arbitrary order, and After= causes a cyclical dependency.

Is there a way to do this in systemd without resorting to checking if a conflict is running inside the ExecStart scripts?

Best Answer

The manual page systemd.unit(5) has this to say about Conflicts=:

Note that this setting does not imply an ordering dependency, similarly to the Wants= and Requires= dependencies described above. This means that to ensure that the conflicting unit is stopped before the other unit is started, an After= or Before= dependency must be declared. It doesn't matter which of the two ordering dependencies is used, because stop jobs are always ordered before start jobs, see the discussion in Before=/After= below.

In other words, just declare an ordering dependency.

Related Question