You are not logged in.

#1 2024-08-29 19:19:22

mesaprotector
Member
Registered: 2024-03-03
Posts: 197

How to properly trap login shell

I think this question fits NC better than anywhere else.

I have a basic (two-line) cleanup script in .bash_logout that I wanted to run on shutdown/reboot as well as an ordinary logout (presumably it shouldn't run on hibernate/suspend which I haven't tested yet). Found a couple stackexchange posts about the issue, one of which suggested the following function which I put in my .bash_profile (not .bashrc because I only want this running when the login shell exits):

exit_session() {
    . "$HOME/.bash_logout"
}
trap exit_session SIGHUP

It half works. To be exact, .bash_logout runs about 80% of the times I shut down, and a good portion of those times the session has trouble exiting - it dumps me into tty1, which I can use just fine, then after 90 seconds kills the user session and shuts down/reboots. I was wondering if SIGHUP was the wrong signal to trap, and replaced it with EXIT. Don't know yet if this solves the issue.

The system journal shows that when the delay happens, it ends when login and then bash are sent a SIGKILL. I also noticed that on shutdowns without a delay, everything is just SIGKILLed immediately which I don't think is supposed to happen.

The original script was as follows:

#
# ~/.bash_logout
#
cat /dev/null > /home/asuka/.local/state/prevwindows &
trash-put -f /home/asuka/.mozilla

Last edited by mesaprotector (2024-08-29 19:20:34)

Offline

#2 2024-08-29 20:04:18

seth
Member
From: Don't DM me only for attention
Registered: 2012-09-03
Posts: 73,800

Re: How to properly trap login shell

Why are your trying to trap anything here?

man bash wrote:

       When  an  interactive  login shell exits, or a non-interactive login shell executes the exit
       builtin command, bash reads and executes commands from the file ~/.bash_logout,  if  it  ex‐
       ists.

A major issue w/ your script is that during a shutdown, the /home partition (assuming you have one) might be unmounted when the login shell gets killed.
Idk what trash-put does but I'd keep whatever /home/asuka/.local/state/prevwindows is in /run/user/$UID which is a tmpfs and supposed to get nuked when your last session terminates (and reboots for sure) so you don't have to worry about clearing it and also "prevwindows" sounds like it get's decent IO, so you can also spare the SSD this way.

Offline

#3 2024-08-29 20:12:48

mesaprotector
Member
Registered: 2024-03-03
Posts: 197

Re: How to properly trap login shell

seth wrote:

Why are your trying to trap anything here?

man bash wrote:

       When  an  interactive  login shell exits, or a non-interactive login shell executes the exit
       builtin command, bash reads and executes commands from the file ~/.bash_logout,  if  it  ex‐
       ists.

A major issue w/ your script is that during a shutdown, the /home partition (assuming you have one) might be unmounted when the login shell gets killed.
Idk what trash-put does but I'd keep whatever /home/asuka/.local/state/prevwindows is in /run/user/$UID which is a tmpfs and supposed to get nuked when your last session terminates (and reboots for sure) so you don't have to worry about clearing it and also "prevwindows" sounds like it get's decent IO, so you can also spare the SSD this way.

The script was not executing on shutdown/reboot without the trap; I don't fully understand how systemctl poweroff works, but it seems that .bash_logout only runs when it receives an explicit "logout" command rather than just being terminated.

My /home (or at least the relevant part of it for this script) is on the same partition I boot from, so that shouldn't be an issue. trash-put moves its arguments to, in this case, ~/.local/share/Trash (it'd be different if it were on another partition). The script runs fully WHEN it runs - it doesn't get hung up trying to execute trash-put.

Last edited by mesaprotector (2024-08-29 20:14:26)

Offline

#4 2024-08-29 20:28:46

seth
Member
From: Don't DM me only for attention
Registered: 2012-09-03
Posts: 73,800

Re: How to properly trap login shell

The shell will exit on a  SIGHUP but might just get a SIGTERM from systemd, so you'd want to trap that, too.

But

man bash wrote:

A trap on EXIT is executed before the shell terminates.

And I generally handle this in zsh's TRAPEXIT function (which does pretty much exactly that, trap EXIT)

Regardless I'd simply keep everything transient that's not meant to survive session or boot on some tmpfs, there're even tools to cache transactional data in a tmpfs and only sync that to disk on a shutdown (to minimize disk writes)
1. it's guaranteed to be gone w/ a reboot (cold boot attacks that literlally freeze the RAM aside)
2. no point in writing stuff to disk that you don't want to keep anyway

Offline

#5 2024-08-29 21:02:40

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,456
Website

Re: How to properly trap login shell

This all strikes me as very odd and not likely a good approach.  But a direct answer to your question is based on the fact that you trap SIGHUP but then you don't properly respond to it.  I suspect the following change may suffice:

exit_session() {
    . "$HOME/.bash_logout"
    exit
}
trap exit_session SIGHUP

This is because the shell is running, and system sends it (along with all other processes) a SIGHUP as part of a normal clean shutdown.  Typically a shell would respond to SIGHUP by shutting down.  But you override that to add something else (but you didn't add, you replaced).  So your shell does not shut down.  Systemd waits 90 seconds, then sends a SIGKILL which is not a great way for your shell to end.

I'm pretty sure systemd should send a SIGTERM in between there as well.  But I don't know if you or some shell tool you are using is similarly trapping that signal.

EDIT: it's quite possible, perhaps even likely, that it's not systemd actually sending the SIGHUP (that struck me as odd as I wrote it).  But systemd may send a SIGTERM to agetty / login which in turn sends a SIGHUP to the shell.  This would explain why no SIGTERM comes to the shell itself.  In any case, the solution is (should be) the same.

Last edited by Trilby (2024-08-29 21:06:04)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#6 2024-08-29 21:09:56

mesaprotector
Member
Registered: 2024-03-03
Posts: 197

Re: How to properly trap login shell

I made only two changes - SIGHUP to EXIT as mentioned above, and I also changed the KillMode of user@.service to control-group; looking back through my logs, it seems that systemd has been very fond of instantly killing everything on shutdown, even before I messed with trapping the signal.

Relevant question here: https://serverfault.com/questions/11377 … y-shutdown

For now it seems to work perfectly. If I have no problems for the next couple days I'll close the thread. You're correct about prevwindows, which I could put on a tmpfs (it's never larger than 3KB or so). I can't do the same with .mozilla, however. It would probably be more robust to just delete it on login instead, but what is .bash_logout for, if not for cleaning out unwanted files at the end of a session tongue

Edit: I'll try Trilby's solution if I need to as well. I'm pretty sure that what systemd is supposed to do is SIGTERM, followed by SIGKILL after 90 seconds (or alternate set timeout).

Last edited by mesaprotector (2024-08-29 21:13:07)

Offline

#7 2024-08-29 21:16:51

seth
Member
From: Don't DM me only for attention
Registered: 2012-09-03
Posts: 73,800

Re: How to properly trap login shell

https://wiki.archlinux.org/title/Firefox/Profile_on_RAM
In doubt you could mount a tmpfs into /home/asuka/.mozilla (before starting FF, otherwise it might open file descritptors on the mountpoint instead of the mount)

Offline

#8 2024-09-09 17:39:55

mesaprotector
Member
Registered: 2024-03-03
Posts: 197

Re: How to properly trap login shell

After ten days, I'm afraid there's still occasionally a hang on shutdown. (I tried to shorten it from 90 to 30s by editing system.conf and user.conf but no luck; would rather it not happen at all anyway.)

The relevant lines in .bash_profile are currently:

exit_session() {
    . "$HOME/.bash_logout"
}
trap 'exit_session; exit' SIGHUP
trap 'exit_session; exit' SIGTERM

On logout only the EXIT signal is sent; on shutdown/reboot EXIT and some inconsistent combination of SIGHUP and SIGTERM are sent, probably because it varies whether the SIGTERM sent by systemd first reaches bash or its controlling process.

If I only trap SIGHUP and not SIGTERM it hangs every time instead of occasionally. I used Trilby's exact syntax, which I'm pretty sure my current version is equivalent to aside from trapping two signals. There might be some kind of odd race condition here that I should probably just avoid by executing these operations on login instead of logout, just... meh, it's annoying.

Trapping EXIT seems to cause trouble with logouts, which is why I'm not currently doing so.

So it turns out the hangs have nothing to do with .bash_logout. Instead, the Multimedia Service Session Manager (wireplumber) is hanging and refusing to stop. This explains why everything worked perfectly from the TTY. It hangs shutdown for 90 seconds, and makes it impossible to log back in on the same TTY as well (switching works).

I should probably make a new thread given this is now unrelated to my original question.

EDIT: https://bbs.archlinux.org/viewtopic.php?id=299271

Last edited by mesaprotector (2024-09-09 19:24:28)

Offline

Board footer

Powered by FluxBB