Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Failed to open file descriptor" on shutdown #50

Open
mesaprotector opened this issue Nov 30, 2024 · 2 comments
Open

"Failed to open file descriptor" on shutdown #50

mesaprotector opened this issue Nov 30, 2024 · 2 comments

Comments

@mesaprotector
Copy link

mesaprotector commented Nov 30, 2024

Apologies if this is not an evsieve issue, but I'm not sure what else it could be.

I use the most recent release version of evsieve, 1.4.0, on Arch Linux; I will soon check if this still occurs at the present commit.

I have a short script that calls evsieve and is run shortly after the X server is up (I boot into tty and use startx).

#!/bin/bash
sleep 3 && 
evsieve --input /dev/input/by-id/usb-ITE_Tech._Inc._ITE_Device_8176_-event-kbd \
	--hook key:numlock exec-shell="sudo -u asuka bash /usr/local/bin/xkbset.sh"

When shutting down, systemd attempts to close all processes. However, it inconsistently (about 1 in 4 times) will log "Failed to open pidfd for process 1812: No such process" or similar, where 1812 is the pid of the bash script, rather than of evsieve itself.

Previously I used to run this script directly in .xinitrc. The error message was slightly different then: "Failed to open pidfd for process 1812: Invalid argument". Every time it occurred it caused the entire user session to get SIGKILLed on shutdown.

Curiously, even if I raise the sleep time to 30 seconds and shut down before evsieve is even run, this still occurs. However, it does not occur if I comment out evsieve, or if I replace it with a different script.

@KarsMulder
Copy link
Owner

KarsMulder commented Dec 3, 2024

Curiously, even if I raise the sleep time to 30 seconds and shut down before evsieve is even run, this still occurs. However, it does not occur if I comment out evsieve, or if I replace it with a different script.

This is indeed curious. If the problem can happen even if evsieve is never ran, then you would think that the problem cannot be anything evsieve does, because it has literally done nothing yet except sitting on the disk. Yet the problem being solved by replacing evsieve by a different script contradicts that assumption...

Anyway, I do not know how you're running the script right now, but

Previously I used to run this script directly in .xinitrc.

is not a good idea, because evsieve does not fork itself. For example if you run

#!/bin/bash
echo "Hello, "
sleep 5
echo "world!"

in a terminal, then you will see that "world!" does not appear for five seconds, because bash does not execute it until the previous command (sleep) has returned. Similarly, if you were to run

#!/bin/bash
echo "Hello, "
evsieve --input /dev/input/by-id/something
echo "world!"

then "world!" would not appear until evsieve exits, such as by specifically sending it a SIGTERM or by its input device disappearing.

So, if you were to invoke evsieve in a .xinitrc or .bashrc, then nothing after the evsieve command would be executed since bash is waiting for evsieve to exit. Even if you put it at the bottom of the init script, I expect things to go wrong because some program is waiting for the init script to finish execution, yet the init script never actually finishes execution because evsieve hasn't finished executing.

I don't know how you're running your script now, but I hypothesize is that you've got an init script that is hanging permanently, causing some core process to not be considered properly initialized, which causes havoc for a reason that I don't know but is easy to imagine.

The officially recommended way to run evsieve in the background is by using systemd. You can do that in a normal bash script by using systemd-run:

#!/bin/bash
sleep 3 && 
systemd-run --service-type=notify --unit=xkbset-on-numlock.service evsieve \
	--input /dev/input/by-id/usb-ITE_Tech._Inc._ITE_Device_8176_-event-kbd \
	--hook key:numlock exec-shell="sudo -u asuka bash /usr/local/bin/xkbset.sh"

Or slightly more properly by writing a systemd unitfile. E.g. create the following file at /etc/systemd/system/xkbset-on-numlock.service:

[Unit]
Description=Invoke xkbset when numlock is pressed.

[Service]
ExecStartPre=/bin/sleep 3
ExecStart=evsieve \
	--input /dev/input/by-id/usb-ITE_Tech._Inc._ITE_Device_8176_-event-kbd \
	--hook key:numlock exec-shell="sudo -u asuka bash /usr/local/bin/xkbset.sh"
Type=notify

[Install]
WantedBy=graphical.target

After creating the above service, you can invoke sudo systemctl daemon-reload && sudo systemctl enable --now xkbset-on-numlock.service to start the service now and have systemd automatically start it during future boots.

@mesaprotector
Copy link
Author

mesaprotector commented Dec 4, 2024

Thank you for your detailed reply. I was also very confused by the error occurring even before evsieve actually runs—my best guess is my bash script was running into an obscure race condition described here
in 2) of the lead email; that is, somehow the script kept getting terminated during the exact window systemd was trying to open a file descriptor for it. (At least that's my only explanation for the syscall returning EINVAL instead of ESRCH.)

And yes, I've been using a systemd service similar to that since shortly before I posted the issue. Since I don't want it to run before the X server is up, the service instead watches a file that gets touched when X starts.

The strangest part of all is that I've been so far unable to reproduce the error with the development version of evsieve, even though nothing else about my setup changed. Which I guess means all is well? If you ever want me to try out 1.4.0 again I'm happy to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants