The explicit CONT on attach is needed in order for wait() to work on older kernels, and the STOP/CONT after attach is better at making bash notice the process is running again.
This causes bash to notice that the process is backgrounded, which prevents it from sending a SIGTERM when the original shell exits.
If the target /doesn't/ properly initialize the terminal after a SIGTSTP/continue (I'm looking at you, emacs), we need to be sure to grab the terminal state before we suspend it and the shell resets the terminal to cooked mode.
This should both cause the target process to redraw / reinitialize the terminal (since it thinks it's been backgrounded and restarted), and should give you back the old terminal, since it sees the process now running in the "background".
These are actually easier -- we just need to TIOCNOTTY, instead of playing games with a dummy child and setsid.
We were letting the child return from fork() and run to the next syscall. This happened to work on my system with 'less', but segfaulted on mutt. Instead, we need to reset the child to before the syscall point, so that none of its code is ever run.