Description of problem: With /etc/udev/rules.d/99-test.rules containing: SUBSYSTEM!="usb", GOTO="test_usb_rules_end" ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="/tmp/test.bash run-add" ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="/tmp/test.bash run-remove" ACTION=="add", ENV{DEVTYPE}=="usb_device", TAG+="systemd", ENV{SYSTEMD_WANTS}="test-add.service" ACTION=="remove", ENV{DEVTYPE}=="usb_device", TAG+="systemd", ENV{SYSTEMD_WANTS}="test-remove.service" LABEL="test_usb_rules_end" And /tmp/test.bash containing: #!/bin/bash echo $0 $@ called by $PPID >> /tmp/test.log One can see from /tmp/test.log that when adding/removing a USB device the RUN rules are executed as expected but only the test-add.service is invoked with systemd even though udevadm monitor --environment --udev prints the expected SYSTEMD_WANTS/TAGS variables when a USB device is removed. The systemd service files used are like: [Unit] Description=Test Add [Service] ExecStart=/tmp/test.bash systemd-add And: [Unit] Description=Test Remove [Service] ExecStart=/tmp/test.bash systemd-remove After few times adding/removing a USB device, /tmp/test.log looks something like: /tmp/test.bash run-add called by 19250 /tmp/test.bash systemd-add called by 1 /tmp/test.bash run-remove called by 19262 /tmp/test.bash run-add called by 19271 /tmp/test.bash systemd-add called by 1 /tmp/test.bash run-remove called by 19283 Version-Release number of selected component (if applicable): systemd-195-2.fc18.x86_64
It is important to realize how "TAG+="systemd", ENV{SYSTEMD_WANTS}=..." works. The "systemd" tag tells systemd to instantiate a *.device unit to match the device as seen by udev. The unit will be in the "active (plugged)" state as long as the device is present. "ENV{SYSTEMD_WANTS}=foo" tells systemd that the *.device unit should have "Wants=" dependency on "foo". As the *.device unit is active, systemd will fulfill this requirement dependency. When the device goes away, it disappears from udev database and systemd stops the *.device unit. Since the device is no more in the database, there's nothing to attach the SYSTEMD_WANTS property to. I don't think it ever makes sense to set ENV{...} on a device that's being removed. Kay, am I right?
Here are two possible workarounds: 1. Use a service with "StopWhenUnneeded=yes". When the device gets unplugged, your service will be stopped. You can take some action in ExecStop. 2. Somewhat more hacky: Run "systemctl start --no-block test-stop.service" from the udev remove rule.
Sounds right. I think we can not start stuff for units that are gone, or are about to go. Systemd wants the device to pull something in, when it's gone, in the current model, we can not instantiate in the context that is no more.
(In reply to comment #2) > Here are two possible workarounds: > > 1. Use a service with "StopWhenUnneeded=yes". When the device gets > unplugged, your service will be stopped. You can take some action in > ExecStop. Right, it generally sounds more fitting to instantiate something ad "add", and let systemd track this unit, and remove exactly this same unit at "remove", instead of creating a new unit, unrelated to the first one, and try to match them together.
OK, I'm closing this as NOTABUG. Let us know if for whatever the reason the provided solution in comment #2 does not work for you.
> 1. Use a service with "StopWhenUnneeded=yes". When the device gets > unplugged, your service will be stopped. You can take some action in > ExecStop. > > 2. Somewhat more hacky: Run "systemctl start --no-block test-stop.service" > from the udev remove rule. Thanks, it was possible to retain the application unchanged by using RUN+="/bin/systemctl --no-block reload-or-restart test-{add,remove}.service" in the udev rules and defining ExecStart/ExecReload/Type/RemainAfterExit in the service files.
Marko, may I know what application it is? It looks like something that would benefit from subscribing to udev events by itself using libudev.
(In reply to comment #7) > Marko, > may I know what application it is? It looks like something that would > benefit from subscribing to udev events by itself using libudev. Thanks for the suggestion, we might investigate that at some point in the future - it's an in-house application running on RHEL/Fedora/Ubuntu at a customer, it interacts with the user after device insertion/removal and then, depending on the user input, proceed changing the state of the system quite drastically. Feel free to ping me over IRC if you want more details.