Avoid I/O via signal-handler thread.

The cleanup code will try to flush the output buffer in some
circumstances, which is not valid if we're handling an async signal
(since it might have interrupted some partial I/O in the main thread).
These signals now set a flag and try to let the main I/O handler take
care of the exit strategy.  Fixes a protocol error that could happen
when trying to exit after a kill signal.
Forward a MSG_ERROR_EXIT value to generator too.
Fixes bug 9882.
Improve logic of code vs exit_code (etc.) in cleanup.