The connect timeout computation could theoretically overflow. However, there was an artificial limit of 60 seconds for connect timeouts. The computation has now been changed to not overflow and the restriction to 60 seconds has been removed.
I noticed during testing that after my changes to catch TERM/QUIT/INT it was no longer possible to kill the streaming kids of the master process. This was obviously bad. However, just removing the signal handlers for the streaming process is bad as well as killing such a process would cause the connection counters to become invalid. So this change handles signals in the streaming process in much the same way as they're handled in the master and monitoring process and attempts to shut the connection down gracefully when catching a signal. This is still not a perfect solution as inconsistencies can arise when the process is killed with a signal that cannot be caught (SIGKILL).
This change implements channel monitoring. In order to try and keep as much of the original code as possible, monitoring is implemented by forking off a separate monitoring process that communicates with the master process using the same means (shared memory) as the shell and connection processes. There is support for both simple TCP connect checking as well as arbitrary health check commands that can be run by the monitoring process.
The original implementation would cause shared memory resource leaks when terminating balance. This is now avoided by marking the shared memory segment as to-be-removed when the last process detaches. This also means that it's easier for the interactive shell to determine the presence of the master process. Furthermore, the code to set up the shared memory segment will now handle the case of a stale and incompatible shared memory segment, which might be left over from a crashed balance instance.
Channels can now be soft- or hard-disabled or enabled. Hard-disabling is a manual process and a hard-disabled channel can only be re-enabled manually. Soft-disabling can be done automatically by balance if it finds a channel to be degraded. Soft-disabled channels can be re- enabled by balance if the channel becomes functional again. But this feature is yet to be implemented.