7

My method for disowning the foreground process takes too much effort.

Suppose I have a process in zsh's foreground. I want to disown it, so I can close the shell without the process being sent a SIGHUP.

At the moment, I start with Ctrl+z to background and pause the process, then

$ disown
disown: warning: job is suspended, use `kill -CONT -32240' to resume
$ kill -CONT -32240
$

then I can close the terminal.

How can I automate that? Ideally, I'd like to be able to press Ctrl+j or something to immediately disown the running process. Or second best, I'd want to be able to run a single command to both disown and SIGCONT the process once it's suspended.

  • 4
    It is easier to bg+disown instead of kill -CONT -1234. – jimmij Aug 15 '15 at 22:11
  • I used to use alias dr='disown -r' in bash. bg and dr do the trick. – Peter Cordes Aug 16 '15 at 14:37
11

Having a global keybind to disown the foreground process is impossible: Keystrokes are received by the foreground process, not by the shell. You need to first suspend it with Ctrl+z if you want to disown it.

However, turns out there's a zsh option to speed up disowning then continuing: With setopt AUTO_CONTINUE, disown will automatically also send SIGCONT.

So you can get it down to C-z disown.

11

When you press Ctrl+Z in a terminal, this causes the foreground process group to receive the signal SIGTSTP (assuming the terminal is in cooked mode and the default key bindings are in place). If the process hasn't set a signal handler for SIGTSTP, this causes the process to be suspended (and even if the process has set a signal handler, it usually only does a small amount of processing before suspending itself). When a process is killed, suspended or resumed, its parent is notified via a SIGCHLD signal; this is what causes the shell to display a new prompt and maybe a message like [1] + 1234 suspended foo. The information flow is
    key → suspension → shell
and not
    key → shell → suspension
so you can't configure a different reaction for Ctrl+Z.

You can set a trap for SIGCHLD, but the trap is not executed when the job is the current foreground job. For the most part, this means that the trap is executed only when a background job terminates, not when the foreground job terminates. But it also means that you can't react to the suspension of the foreground job.

You can indirectly react to changes in background jobs by setting a precmd hook that compares the job states with states saved from the previous precmd run. But I don't know what you could do with that: there can only be a single suspend key, so you need some extra information to know whether the process was meant to be paused, backgrounded or disowned.

I've set up zsh so that pressing Ctrl+Z at an empty prompt backgrounds the current job. This lets me press Ctrl+Z twice to put the foreground job into the background with only a short suspension.

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z

You could make it call disown if you like. Or you could arrange for a third Ctrl+Z to call disown with the following untested modification.

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    if (($fancy_ctrl_z_already_bg)); then
      disown
    else
      bg
      fancy_ctrl_z_already_bg=1
    fi
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
fancy_ctrl_z_precmd () {
  fancy_ctrl_z_already_bg=0
}
precmd_functions+=fancy_ctrl_z_precmd
  • Note that you don't need the full cooked mode for ^Z to work. isig is enough (even without icanon) – Stéphane Chazelas Aug 17 '15 at 14:35
  • So the SIGTSTP is sent by the terminal emulator? Is it possible to configure the emulator (any that you know) to change what it does for a ^Z? Like in the shortcut preference? – Franklin Yu May 1 '17 at 4:58
  • @FranklinYu The terminal emulator sends SIGTSTP when you press Ctrl+Z while a program is running and the feature is activated in the terminal interface (stty +isig). You can change which character triggers this with the stty command (you can't set an arbitrary key, it has to be a single byte, not an escape sequence). While the shell is in the foreground, it changes the terminal settings to take over key presses so the effect of Ctrl+Z depends on the shell's key bindings. – Gilles May 1 '17 at 9:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.