ZSH exits with the return code of the last command instead of 0, breaking `remain-on-exit failed` in tmux

Viewed 45

The remain-on-exit failed option in tmux causes the pane to remain open when exit code isn't 0, to allow me to inspect what happened. In interactive mode, I would expect zsh to always return 0 unless it crashes or is killed. However, this is not what happens.

Example: If I press Ctrl+C to cancel inputting the current line, and subsequently press Ctrl+D, zsh exits with error code 130 instead of 0.

Doing an echo $? and experimenting confirms that after pressing Ctrl+D, zsh is simply returning the exit code of the last command executed, fooling tmux into thinking that it crashed, which is not the case.

How can I change this behavior, and- should I? Would doing so break anything?

2 Answers

When any process terminates because it had been killed by a signal, Linux ensures that there a non-zero exit code (larger than 127) is set. The exit code is 128+SIGNALNUMBER; in your case, the signal is 2 (SIGINT), which results in exitcode 130.

However, some signals can be caught. You could catch the catchable signals (using the trap command) and do a graceful exit. For instance to catch SIGINT in this way, you would do it by

trap 'exit 0' INT

This appears to set the final shell return code to 0 when added to ~/.zshrc:

exitzero() {
  print "in exitzero for process $$"
  exit 0
}
add-zsh-hook zshexit exitzero

The print statement is optional; it's just an indicator and has no effect on the return code.

With the call to add the hook in .zshrc, it should only be set for interactive shells, so that should limit its effects. The documentation in the zshmisc man page indicates that the zshexit hook is only invoked in a limited set of scenarios:

Executed at the point where the main shell is about to exit normally. This is not called by exiting subshells, nor when the exec precommand modifier is used before an external command. Also, unlike TRAPEXIT, it is not called when functions exit.

I have no idea what other impacts this code might have. It seems to be a relatively low-risk change - if you try it, please let us know how it works.

Related