Hackery on bash
I've always been vaguely annoyed by bash(1)
's options for notifying you of the termination of background jobs. There are two options, and neither one is very sensible.
In the default mode, termination notifications are printed just before displaying the primary prompt. So if you start a background task (say, a GUI application) from the command line, do some stuff in it, then terminate it and start it again from the same command line, the chances are that the termination notification for the first instance isn't printed until after you start the second one – and one particularly silly consequence of this is that the job number doesn't get reused, even though you're running the same process over and over again and no two runtimes overlap.
There's an alternative mode, which is asynchronous notification (set -b
or set -o notify
). In this mode, every time bash receives SIGCHLD to tell it a job has changed state, the signal handler itself prints the notification, irrespective of what the terminal was up to in the main process. So in this mode, a job terminating while you're at a command prompt will move the cursor to somewhere readline wasn't expecting it, and corrupt your display; and also these notifications can go off when you're in the middle of another foreground process, and disrupt the display in that. This has never struck me as a sensible price to pay for the convenience of prompt notification.
How I've always wanted bash to do this is the VMS way. If you're in the middle of editing a command line, and a background job terminates, then bash should print the termination notification on a new line, and then redisplay the command line you were in the middle of editing and allow you to carry on editing it. It should do this with the full knowledge and consent of readline, so that no display corruption takes place. If a job terminates while another foreground task is running, then ideally I'd like that foreground task to receive the notification and display it in an appropriate manner, but that's unrealistic for anything that isn't actually VMS so I'll settle for seeing the notification before the next bash prompt instead.
Some years ago I actually implemented this mode in bash, but I didn't know a lot about safe signal handling and my implementation contained several unpleasant race conditions. I used it in spite of that for a while, but never felt that it was good enough to distribute any further.
The other week I happened to be reading the libreadline documentation, and I discovered that there is actually a callback-based interface to readline. You call a readline setup function, then you select(2)
between stdin and other stuff and call another readline function whenever stdin is readable, and when a complete line is available this function calls you back and you can call a readline termination function. So it is possible to use readline in a context where you're also listening to other fds at the same time – and in particular, I can use this together with an intra-process pipe to communicate SIGCHLDs from the signal handler back to the main bash thread, and guarantee that job termination notifications will always be printed at a time when bash is ready to deal with them without data corruption.
So I've now reimplemented my old bash hack, in a manner that I think ought to be decently safe. Now I need to work out what to do with it next. I think probably the best thing is if I start by using it myself wherever I use bash, and give it some actual testing before I try submitting it to either the Debian folk or the real bash maintainers…
If anyone else has always wanted this behaviour – it seems incredible to me that it isn't considered the Obviously Right Thing – then some help in testing it would be appreciated :-)