davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Can't write to a file from udev Run+=

Fri Apr 06, 2018 11:37 am

rpi zero w, stretch-lite

I have a udev rule that matches when a bluetooth device disconnects:

Code: Select all

ACTION=="remove", KERNEL=="input[0-9]*", RUN+="/home/pi/bt_disconnected"
The script bt_disconnected runs when the device is disconnected, but fails if it tries to write to a file. Here's the script:

Code: Select all

#!/bin/bash

logger "Disconnected"
logger "$(whoami)"
echo "hello"  >> "/home/pi/disconnects"
The script runs, reports user "root", then fails with exit code 1 without writing to the file.

So, when run from the udev rule, the user is "root". Outside the udev environment, the script will write to the file /home/pi/disconnects whether run as pi or root (Its permissions are 777)

I've seen posts where this issue was caused by trying to write to a file directly in the RUN+= argument and assuming a shell environment was in place. But, moving the commands to a file with the appropriate shebang (#!/bin/bash) is supposed to fix that issue. But, I also tried invoking from the udev rule using bash:

Code: Select all

ACTION=="remove", KERNEL=="input[0-9]*", RUN+="bash /home/pi/bt_disconnected"
Same result.

Someone else has the same issue with no replies here:

https://stackoverflow.com/questions/491 ... ile-system

What I'm trying to do---

Simply keep a count of disconnect events. I have a separate script running that continually tries to connect to a specific bluetooth device. If N disconnects occur within a period of time (a user is manually disconnecting from the device end), then the autoconnect script should quit trying to connect and remove the associated device using bluetoothctl

I can't figure out a way to do it from a script run from the udev rule, since it can't seem to write to a file to keep a disconnect event count.

Also, I can't seems to affect the udev environment, even when the script is sourced from the RUN+=. So that approach seems like a dead end too.

Any help would be appreciated!

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Fri Apr 06, 2018 2:37 pm

Found a workaround:
sudo /etc/init.d/udev restart
Apparently, the filesystem as seen by udev is read-only until that command is executed. Doesn't make much sense to me, but it works!

Got the idea from this post:

Code: Select all

https://askubuntu.com/questions/883843/udev-rules-scripts-has-only-read-only-access-to-ubuntu16-10
Seems like a bug?

User avatar
DougieLawson
Posts: 41900
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: Can't write to a file from udev Run+=

Fri Apr 06, 2018 7:50 pm

It's not a bug, it's a design feature/design limitation.

udev is used to make sure all devices are online before the filesystems are mounted, so it's pretty much impossible to be sure a filesystem is writable when the udev rules run at boot time.

The same is true if you tried to write to a USB filesystem when you plug in the device. udev is the process that detects the USB stick being inserted.

There are better ways to get things started at boot time that can be run when the system is alive and all filesystems are mounted read-write. Take a look at writing a systemd service file.
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on Twitter/LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Fri Apr 06, 2018 10:26 pm

Thanks for the reply, but--

The filesystem is forever read-only (as seen by udev), not just at boot time. Any time the rule triggers, even hours after reboot. Restarting udev once in /etc/rc.local fixes the issue.

Sure, I could poll from a systemd service to look for the bluetooth disconnect/connect sequence. But, I think using udev to run a script on bt disconnect is a better solution--even with the workaround of having to restart udev after rebooting.

Seems like a bug to me.

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Fri Apr 06, 2018 11:01 pm

Rereading your post--maybe you meant the restart of udev would be better done in a system service, rather than in /etc/rc.local? I would agree with that! I think it's always better to use a service rather than launching scripts in /etc/rc.local, .bashrc, etc.

I was just making the point that given the reset in rc.local makes the filesystem R/W, something is going wrong in the boot sequence that's leaving the filesystem (as seen by udev) as readonly. Probably some race condition in the services that are started during boot.

User avatar
DougieLawson
Posts: 41900
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: Can't write to a file from udev Run+=

Fri Apr 06, 2018 11:58 pm

You need to look deeper at why a udev restart is needed.

There's already a couple of services
systemd-udev-trigger.service loaded active exited udev Coldplug all Devices
systemd-udevd.service loaded active running udev Kernel Device Manage

There's also
systemd-udevd-control.socket loaded active running udev Control Socket
systemd-udevd-kernel.socket loaded active running udev Kernel Socket

Those sockets are used by udevadm, to give you an external control of udev.

How about running the script that writes your files with disown (so it gets started by udev, but then disowns to become a free running task). That way you can add a sleep so that the filesystem is mounted R/W when that delay ends and the rest of the script runs. Those scripts won't get killed by udev when they run over the udev time limit.

https://askubuntu.com/questions/646011/ ... ev-rules-d
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on Twitter/LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 11:00 am

You need to look deeper at why a udev restart is needed.
So, that implies to me that the filesystem should NOT be readonly (for udev) after boot? So, normally the file system should be read/write after boot? And that there must be a bug somewhere if it is?

Any suggestion on how to do that (look deeper)? Are you thinking it's my udev rule that's causing the filesystem to become readonly for udev? I don't see the record in /var/log/syslog that gets written when the udev rule is triggered (for some reason, that record is written by logger, even when the filesystem seems to be readonly for udev)

I'll try removing the udev rules, rebooting, then adding them after the boot and seeing if the writes are successful when they are triggered. Pretty sure I've done that already, but I'll repeat to make sure.

I could try further qualifying the rule to make sure it doesn't trigger during boot, if triggering during boot causes the problem.

The script that runs when I connect via bluetooth (long after boot and long after the file system is readonly for udev) is very short. It only appends one record to a file in /tmp and logs to /var/log/syslog using logger. So it won't exceed any udev timelimit.

I'll look at the services. I'm assuming one or both provide a mechanism to launch a script when a bluetooth device disconnects? That would be perfect!

Thanks

User avatar
DougieLawson
Posts: 41900
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 11:06 am

First thing I'd do is get a second SDCard so you can build a "throw-away" system that can be mucked about with and when you break it you can start again from a fresh Raspbian download. That removes the risk of leaving your normal system unbootable.

Set that up with exactly the same stuff you've got now and see what happens.

https://wiki.ubuntu.com/DebuggingUdev gives some hints of how to debug udev.
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on Twitter/LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 11:06 am

Reading your posts again, perhaps you were assuming the script triggered by udev was trying to write to a newly attached device.

Just to clarify, all the script does is append a record to a file in /tmp. Another service will (not running yet) will read that file and decide whether to attempt to reconnect, or stop trying.

So, there shouldn't be any timing issues associated with the rule getting triggered and a device being ready for access.

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 11:11 am

DougieLawson wrote:
Sat Apr 07, 2018 11:06 am
First thing I'd do is get a second SDCard so you can build a "throw-away" system that can be mucked about with and when you break it you can start again from a fresh Raspbian download. That removes the risk of leaving your normal system unbootable.

Set that up with exactly the same stuff you've got now and see what happens.

https://wiki.ubuntu.com/DebuggingUdev gives some hints of how to debug udev.
So, what I have now (restart udev in rc.local) is working after dozens of reboots, no issues.

Yes, if it's agreed there is a bug somewhere, I can flash a new image and add the minimum required to trigger the udev rules. That's probably the bluetooth agent and associated scripts. There's not much on the image besides that anyway--just the configuration required to support the pHat DAC.

User avatar
DougieLawson
Posts: 41900
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 11:41 am

davethomaspilot wrote:
Sat Apr 07, 2018 11:11 am

So, what I have now (restart udev in rc.local) is working after dozens of reboots, no issues.
That's what software professionals call a "fudge" or a "work-around". Those things tend to bite you hard in your tail-end sometime in the future (often at 3:00am).
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on Twitter/LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 11:46 am

Don't I know it. (Developed software for a living for decades)

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 8:00 pm

Another user which seems like the same issue on rpi, stretch:

https://unix.stackexchange.com/question ... le_rich_qa

I'll try duplicating the issue on a clean stretch lite image, as suggested.

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 8:51 pm

Duplicated same issue on a fresh install of 3/13/2018 stretch-lite. Only things done to the "stock" image:

headless config--added wpa_supplicant.conf and ssh file to /boot
raspi-config stuff
added /home/pi/.ssh directory (for ssh keys)

Created a bt_connected script in /home/pi:

Code: Select all

#!/bin/bash
logger "Bluetooth Connected"
Created a bt_disconnected script in /home/pi:

Code: Select all

#!/bin/bash
logger "Bluetooth Disconnected"
echo "hello" >> /tmp/disconnects
After booting, added the udev rules to /etc/udev/rules.d/99-bt.rules:

Code: Select all

ACTION=="add", KERNEL=="input[0-9]*", RUN+="/home/pi/bt_connected"
ACTION=="remove", KERNEL=="input[0-9]*", RUN+="/home/pi/bt_disconnected"
Did not reboot.

Same issue. The logging to /var/log/syslog always works, but the append fails with a return code of 1:

Code: Select all

Apr  7 20:32:21 Ipad2GMA kernel: [  838.044177] input: A4:F1:E8:B6:2E:72 as /devices/virtual/input/input5
Apr  7 20:32:21 Ipad2GMA root: Bluetooth Connected
Apr  7 20:32:21 Ipad2GMA systemd-udevd[685]: Process '/usr/sbin/th-cmd --socket /var/run/thd.socket --passfd --udev' failed with exit code 1.
Apr  7 20:32:29 Ipad2GMA root: Bluetooth Disconnected
Apr  7 20:32:29 Ipad2GMA systemd-udevd[690]: Process '/home/pi/bt_disconnected' failed with exit code 1.
The message:

Code: Select all

Apr  7 20:32:21 Ipad2GMA systemd-udevd[685]: Process '/usr/sbin/th-cmd --socket /var/run/thd.socket --passfd --udev' failed with exit code 1.
maybe a hint, but that message occurs in /var/log/syslog, without or without my udev rules being added when the bluetooth connect occurs.

Doing a restart of udev cleans everything up:

Code: Select all

Apr  7 20:42:35 Ipad2GMA systemd[1]: Stopping udev Kernel Device Manager...
Apr  7 20:42:35 Ipad2GMA systemd[1]: Stopped udev Kernel Device Manager.
Apr  7 20:42:35 Ipad2GMA systemd[1]: Starting udev Kernel Device Manager...
Apr  7 20:42:35 Ipad2GMA systemd[1]: Started udev Kernel Device Manager.
Apr  7 20:42:49 Ipad2GMA kernel: [ 1466.761426] input: A4:F1:E8:B6:2E:72 as /devices/virtual/input/input6
Apr  7 20:42:50 Ipad2GMA root: Bluetooth Connected
Apr  7 20:42:50 Ipad2GMA systemd-udevd[742]: Process '/usr/sbin/th-cmd --socket /var/run/thd.socket --passfd --udev' failed with exit code 1.
Apr  7 20:42:59 Ipad2GMA root: Bluetooth Disconnected
(There's no message about bt_disconnected failed with exit code 1, and the record gets appended to /tmp/disconnects)

Isn't it safe to conclude that something is happening during boot that makes the filesystem readonly (for udev)? At boot time, there was nothing but "out of the box" stuff. Adding my own rules with an editor after boot is the only way I know to duplicate the issue. Suggestions for another way to test what the filesystem looks like to a script executed from a udev RUN+= are welcom.

I keep adding "for udev", because I can always write to the file as either user pi or user root. But while a "whoami" reports "root" in the scripts, writes to everyplace I've tried fail until I do the restart. But, logger always works!

davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 8:59 pm

I see this record when I do dmesg:

[ 1.448736] VFS: Mounted root (ext4 filesystem) readonly on device 179:2.


Is this normal?

User avatar
DougieLawson
Posts: 41900
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: Can't write to a file from udev Run+=

Sat Apr 07, 2018 9:58 pm

I think you should create an issue at https://github.com/raspberrypi/linux/issues for this.
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on Twitter/LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.


davethomaspilot
Posts: 122
Joined: Tue Apr 29, 2014 6:18 pm

Re: Can't write to a file from udev Run+=

Tue Apr 10, 2018 12:06 pm

I found a script that uses inotify to turn off wifi when a bluetooth device connects (and vice-versa). I can hack it to execute the commands I want at bluetooth disconnect time.

Code: Select all

case $1 in
start)
while true
do
        RES=`inotifywait -q -e CREATE,DELETE /dev/input/`
        case "$RES" in
                "/dev/input/ DELETE event0")
                        ifconfig wlan0 up
                        date +%s >> /tmp/disconnects
                ;;
                "/dev/input/ CREATE event0")
                        ifconfig wlan0 down

                ;;
        esac
done &
;;
esac
install inotify
cmd: sudo apt-get install inotify-tools
cp inotify.txt to /etc/inet.d/inotify ( rename from inotify.txt to inotify ! )

inotify.txt

make it executable
cmd: sudo chmod u+x /etc/init.d/inotify
create symlinks to start script at boot
cmd: sudo update-rc.d inotify defaults

Hope this helps.
Thanks to spalthammer on this thread!

https://github.com/raspberrypi/linux/issues/1402

Return to “Advanced users”