Does bash have a hook to determine when child shell exits?

7

In bash I spin up a t/csh shell, which updates the tty input (stty erase ^H) in the .cshrc, but when exit-ing and returning to bash the backspace key no longer works. This is because bash uses readline and I need to reset the erase (stty erase ^?).

If I understand trap correctly, it seems like I could trap the t/csh exit from within the t/csh process, and run commands after it exits. However, my preference would be for the trapping to occur in bash, which ideally would detect a shell was called/exited and then run a script to reset its configurations.

This is preferred because I could call any number of shells (e.g., dash, zsh), which may inadvertently modify bash-specific settings. Instead of maintaining multiple trap commands for each shell, it seems like it would be best to have one for bash.


Is my understanding of trap correct? If so, is it possible for bash to detect a child shell exit and then run a script?

vol7ron

Posted 2017-05-05T16:25:37.213

Reputation: 403

Answers

7

You were on the right track with trap. What you want is the following:

trap "stty erase ^?" SIGCHLD

You can add that to .bashrc. Note that this will run when any subprocess ends.

This will only work in interactive sessions. For non-interactive sessions, bash will not enable job control by default, so you will need to run set -o monitor first. But I doubt you'd need backspaces in non-interactive scripts.

SIGCHLD is sent to the parent process whenever a subprocess exits.


An alternative method is to wrap your other shell in a script, such as:

#!/bin/sh
tcsh
stty erase ^?

Then, if you launch your shell through the script, the script will run the stty erase command after the shell exits. This is less likely to have side effects than a global trap handler, but of course it'll only work if you launch through the script every time (or create an alias to do so, e.g. alias 'tcsh' '~/launch-tcsh.sh').

Floofy Fox

Posted 2017-05-05T16:25:37.213

Reputation: 86

I suppose for tty settings, the job/control isn't as big a deal, but everything else that is probably a very important point. My guess is there's a way to detect the child process and only do this trap if it's a different shell, but this is exactly what I was hoping for -- I was skeptical, but I'm glad I asked -- thank you! – vol7ron – 2017-05-05T17:19:19.253

@vol7ron Unfortunately, there isn't a foolproof way to detect what the child process was, from bash. You can use jobs -n to get recently exited jobs and hopefully the last one is correct, but there exists a race condition there. I think you might be better off using the script wrapper alternative instead. – Floofy Fox – 2017-05-06T16:00:27.250

1I would have thought that the easiest way to enter ^? is to type the ^ character then the ? character: stty understands that the ^ character is a prefix for a control character. Also, you could use the Control-V Backspace to tell Vim that you want to insert a literal Backspace character. – Adrian Pronk – 2017-05-08T02:56:42.053

@AdrianPronk Thanks, didn't know stty did that. Had the vim literal one working at one point but then stuffed something up. Anyway, edited. – Floofy Fox – 2017-05-08T04:20:27.253