[systemd-devel] Can't manage to start a task when bluetooth is ready with systemd

Andrei Borzenkov arvidjaar at gmail.com
Mon Aug 16 18:14:07 UTC 2021


On 16.08.2021 18:20, Gildas Bayard wrote:
> Hello,
> 
> I've first posted on stackoverflow but couldn't get any usefull answer
> (gomenasai 😅)
> 
> I'm trying to start a task when bluetooth is ready on a raspi (running
> raspbian 10 - buster) with systemd. I've added the file
> /etc/systemd/system/my.service with this content
> 
>    |[Unit] After=bluetooth.target Requires=bluetooth.target [Service]
>    Type=idle ExecStart=/root/my.sh [Install] WantedBy=multi-user.target |
> 

This is unreadable.

> Then I used the sudo systemctl enable my.service command, and rebooted.
> 
> After reboot I look at services launch order with |systemd-analyse
> plot|, and it turns out that my service starts after bluetooth.target as
> expected. But bluetooth.target gets started very early (attachment
> bt1.svg). And |systemctl show bluetooth.target| tells me
> 'After=bluetooth.service' so why is bluetooth.target point is reached
> way before bluetooth.service?
> 

Because bluetooth.service is started only if bluetooth devices are
present (ConditionPathIsDirectory=/sys/class/bluetooth). When your
service pulls in bluetooth.target it happens very early, before
bluetooth devices are present, so systemd skips starting of
bluetooth.service. But that is not failure so bluetooth.target is
"started". Later bluetooth.target get start request once more from udev
rule, and this causes second attempt to start bluetooth.service that now
is actually activated.

> I precise that if I use
> 
>    |[Unit] After=bluetooth.service Requires=bluetooth.service|
> 

Would you please apply minimal efforts to write your messages so that
they can be read normally.

> it's also weird: my service is started early, way before
> bluetooth.service and bluetooth.target (which as expected is activated
> rigth after bluetoothd is ready, attachment bt2.svg).
> 
> Could you tell me what's wrong?
> 

Exactly the same. systemd skips starting bluetooth.service early when
your my.service pulls it in. This is not failure, so my.service is
started. Later bluetooth.service gets started by udev rule.

This is the same old fundamental misunderstanding - systemd dependencies
are between jobs, not between units. After=bluetooth.service in
bluetooth.target does not mean bluetooth.target will be activated after
bluetooth.service - it means *start job* for bluetooth.target will be
selected for execution after *start job* for bluetooth.service has
finished. That start job for bluetooth.service did not actually start it
is irrelevant. Start job did not fail so dependent jobs were not cancelled.

Actually this is excellent example how easily systemd dependency system
breaks apart as soon as it hits anything that goes beyond simple "start
these scripts in defined order during system boot". In this case it
trips over conditional start.

The practical solution in your case is to make your service
WantedBy=bluetooth.target and After=bluetooth.service.


More information about the systemd-devel mailing list