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

SIGHUP signal not raises exit immediately #5381

Closed
FlyingWombat opened this issue May 1, 2024 · 15 comments · Fixed by #5399
Closed

SIGHUP signal not raises exit immediately #5381

FlyingWombat opened this issue May 1, 2024 · 15 comments · Fixed by #5399

Comments

@FlyingWombat
Copy link

FlyingWombat commented May 1, 2024

I'm not sure if this is an alacritty issue, or a xonsh issue, so I'm starting here.
When using alacritty in single-instance mode, xonsh processes remain if their parent window is closed by the window manager (e.g. Meta+Q for Sway). I've only been able to find this issue when using both alacritty in single-instance mode and xonsh. Alacritty single-instance with Zsh works as expected, alacritty individual instances works with xonsh, and xonsh with foot's single-instance mode works. The issue also does not occur if xonsh has a parent process other than alacritty (e.g. alacritty -> zsh -> xonsh)

Expected Behavior

Xonsh processes should exit when parent window closes.

Current Behavior

Xonsh process remains when parent window is closed.

Steps to Reproduce

  1. export SHELL=$(which xonsh) if xonsh isn't your default shell.
  2. Start an alacritty instance with alacritty --socket /tmp/alacritty.sock
  3. Create a second alacritty window with alacritty msg --socket /tmp/alacritty.sock create-window. This creates a new terminal attached to the same instance of alacritty. Notice now there are two xonsh processes attached to the same alacritty process.
  4. (optional) run some command in the second terminal window to help identify it (e.g. man bash).
  5. Close the second terminal window using the window manager instead of exiting xonsh directly. Notice there are still two xonsh processes attached to the alacritty process.

xonfig

+------------------+----------------------------------+
| xonsh            | 0.16.0                           |
| Python           | 3.11.9                           |
| PLY              | 3.11                             |
| have readline    | True                             |
| prompt toolkit   | 3.0.40                           |
| shell type       | prompt_toolkit                   |
| history backend  | sqlite                           |
| pygments         | 2.17.2                           |
| on posix         | True                             |
| on linux         | True                             |
| distro           | unknown                          |
| on wsl           | False                            |
| on darwin        | False                            |
| on windows       | False                            |
| on cygwin        | False                            |
| on msys2         | False                            |
| is superuser     | False                            |
| default encoding | utf-8                            |
| xonsh encoding   | utf-8                            |
| encoding errors  | surrogateescape                  |
| xontrib 1        | vox                              |
| xontrib 2        | coreutils                        |
| xontrib 3        | voxapi                           |
| RC file 1        | /etc/xonsh/xonshrc               |
| RC file 2        | /home/wombat/.config/xonsh/rc.xsh |
+------------------+----------------------------------+

System

Distro: Nixos
WM: Sway 1.9
Alacritty: 0.13.2

For community

⬇️ Please click the 👍 reaction instead of leaving a +1 or 👍 comment

@anki-code

This comment was marked as outdated.

@anki-code
Copy link
Member

anki-code commented May 3, 2024

JFYI to trace this you can use this message - #5361 (comment)

@FlyingWombat

This comment was marked as outdated.

@anki-code

This comment was marked as outdated.

@FlyingWombat

This comment was marked as outdated.

@anki-code

This comment was marked as outdated.

@FlyingWombat
Copy link
Author

Error: Custom { kind: ConnectionRefused, error: "invalid socket path "/tmp/alacritty.sock"" }

Strange. Maybe Mac has some weird rules about where sockets can be. The socket can be anywhere, I just used /tmp/ for an example.

Using the signal-catch.py example, with export SHELL="$PWD/signal-catch.py", it appears that alacritty is sending a SIGHUP when the window is closed. But, that simple check doesn't show any different behavior between alacritty running normally (one process per window) and in single-instance (one process all windows); it just shows a single SIGHUP for ether one.

Turns out the strace logs are much shorter on Arch Linux (only 250 lines), so I'm attaching them here.

Regular alacritty (xonsh closes):
xonsh-strace-normal-closes.txt

single-instance (doesn't close):
xonsh-strace-daemon-noclose.txt

@anki-code
Copy link
Member

anki-code commented May 6, 2024

Good catch @FlyingWombat !

alacritty is sending a SIGHUP when the window is closed

And:

SIGHUP ("signal hang up") is a signal sent to a process when its controlling terminal is closed.

Next you can run xonsh in debug mode in IDE, then run kill -SIGHUP <pid>(doc) and review what xonsh is doing with this signal. The start point is looking for signal.signal(...) (set signal handler) and signal.SIGHUP lines (Cmd+Shift+F to search substring around the whole code).

@anki-code anki-code changed the title Xonsh ignores alacritty kill signal Xonsh ignores alacritty SIGHUP signal May 6, 2024
@anki-code
Copy link
Member

anki-code commented May 7, 2024

I got this on mac:

# Terminal 1
xonsh --no-rc  

# Terminal 2
ps ax | grep 'xonsh --no-rc'
# xonsh pid 100
kill -SIGHUP 100

# Terminal 1
#zsh: hangup     xonsh --no-rc

# Terminal 2
ps ax | grep 'xonsh --no-rc'
# xonsh in S (sleep) state and pid is 101

On the second try:

# Terminal 1
xonsh --no-rc   # pid 123

# Terminal 2
kill -SIGHUP 123

# Terminal 1
# ...
#  File "/Users/pc/.local/xonsh-env/lib/python3.12/asyncio/base_events.py", line 685, in run_until_complete
#    return future.result()
#           ^^^^^^^^^^^^^^^
#  File "/Users/pc/.local/xonsh-env/lib/python3.12/site-packages/prompt_toolkit/application/application.py", line 649, in run_async
#    assert not self._is_running, "Application is already running."
#AssertionError: Application is already running.
#Xonsh encountered an issue during launch
#Failback to /bin/zsh

It looks like there is no catching and processing SIGHUP signal. PR is welcome!

@anki-code anki-code changed the title Xonsh ignores alacritty SIGHUP signal Support SIGHUP signal May 7, 2024
@anki-code anki-code added the v1 label May 7, 2024
@anki-code
Copy link
Member

anki-code commented May 7, 2024

I've understood the case:

  1. When you send SIGHUP this handler is working (line 62 do sys.exit()):

xonsh/xonsh/built_ins.py

Lines 47 to 64 in 4a2cfc6

if ON_POSIX:
sigs += (signal.SIGTSTP, signal.SIGQUIT, signal.SIGHUP)
return sigs
def resetting_signal_handle(sig, f):
"""Sets a new signal handle that will automatically restore the old value
once the new handle is finished.
"""
oldh = signal.getsignal(sig)
def newh(s=None, frame=None):
f(s, frame)
signal.signal(sig, oldh)
if sig != 0:
sys.exit(sig)
signal.signal(sig, newh)

  1. The sys.exit() function in fact just raises SystemExit exception.

  2. This exception catched by the shell e.g. ptk:

except (KeyboardInterrupt, SystemExit):
self.reset_buffer()

  1. And nothing happends on first SIGHUP.

We need to pass forward the SystemExit futher.

Nice catch. I will prepare PR to fix this. Thank you for reporting @FlyingWombat !

@anki-code anki-code changed the title Support SIGHUP signal SIGHUP signal not raises exit May 7, 2024
@anki-code anki-code changed the title SIGHUP signal not raises exit SIGHUP signal not raises exit immediately May 7, 2024
@anki-code
Copy link
Member

anki-code commented May 7, 2024

@FlyingWombat could you please try #5399?

xpip install -U --force-reinstall git+https://github.com/xonsh/xonsh@sig_exit_fix

@anki-code
Copy link
Member

anki-code commented May 8, 2024

Originally posted by @FlyingWombat in #5399 (comment):

Tried this out, and while it is exiting when sent SIGHUP now, it doesn't always exit properly. What I noticed is, after xonsh exits, zsh no longer recognizes Ctrl+C.

When kill -SIGHUP 1234 is run from xonsh itself, it exists correctly (zsh works fine after). But running kill -SIGHUP 1234 from another terminal running e.g. zsh, goes like this:

# running zsh, launch xonsh
xonsh on  sig_exit_fix [?] via 🐍 v3.12.3 (.venv)
❯ xonsh

# send SIGHUP
(.venv) wombat@wombat-pc ~/builds/dev/xonsh sig_exit_fix @ 
%

xonsh on  sig_exit_fix [?] via 🐍 v3.12.3 (.venv) took 14s
❯ ^C^C
# zsh no longer recognizes Ctrl+C

If I do the same thing with bash, zsh is working properly afterwards.

@anki-code
Copy link
Member

anki-code commented May 8, 2024

@FlyingWombat thanks for help!
I can repeat this on Mac with iTerm2 or Alacritty:

# Terminal 1
# Run iTerm or Alacritty with zsh as default shell
xonsh -DFFF=1

# Terminal 2
ps ax | grep FFF  # xonsh pid 123
kill -SIGHUP 123

# Terminal 1
# Return zsh
# Ctrl+C is not working and Mouse Scroll produces `10M35;`
stty sane
# Everything is working

It looks that in 5399 I solved exit code issue and xonsh exit is correct but something is needed to restore terminal state.

The readline shell type works good after catching signal so we need to fix PTK:

# use the latest commit from 5399
xpip install -U --force-reinstall git+https://github.com/xonsh/xonsh@sig_exit_fix
xonsh -st readline

@anki-code
Copy link
Member

anki-code commented May 8, 2024

@FlyingWombat I fixed stty state for ptk, please test again:

xpip install -U --force-reinstall git+https://github.com/xonsh/xonsh@sig_exit_fix
# restart xonsh
xonfig 
# Git SHA | 5fa579a # https://github.com/xonsh/xonsh/pull/5399/commits

@FlyingWombat
Copy link
Author

Exit signals are working with that PR. Thanks for your help!

@anki-code anki-code removed the v1 label May 9, 2024
gforsyth pushed a commit that referenced this issue May 13, 2024
### Before

Case 1: Handler catches the exit signal and do not pass it forward. As
result xonsh could be suspended by OS or crash. Also exit code is wrong.
See repeatable examples with SIGHUP in
#5381 (comment).

Case 2: From bash/zsh as login shell run xonsh. Then send quit signal to
xonsh. The terminal state will be broken: disabled SIGINT, mouse pointer
produces mouse state codes.

### After

Case 1: Xonsh exit normally with right exit code. Fixed #5381 #5304
#5371.

Case 2: After exiting with right exit code the state of the terminal is
good.

## For community
⬇️ **Please click the 👍 reaction instead of leaving a `+1` or 👍
comment**

---------

Co-authored-by: a <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants