Like in ZK, do not call into the handle to get the state, instead just return the state we cache anyway. This will prevent deadlocks when things are trying to find out our state as we're closing. Also change wait_until_connected to break if we go into @_shutting_down or @_closed state, and be more accurate around the timeout value (treat it as a deadline).
only try to realize the truth there is no lock Actually, that's not true. We swap out @czk for nil, and spin up the shutdown thread to close the connection, but without holding onto the mutex. Since everything is accessing @czk through #czk, they'll get a NotConnected exception as soon as its nilled out. This reduces the chances of deadlock during a potentially hangy operation (shutdown of the underlying connection). Also, insert a hard-coded 30 second tiemout while waiting on the shutdown thread to prevent hanging forever in the case of unforseen catastrophe
No operation should ever block for more than the session timeout value (which is currently hardcoded to 20s in zkrb.c). If a thread has been sleeping for more than 30s wake it up with an exception to prevent hanging forever.
Instead of keying off ZKRB_RUBY_187, do an actual check for the availability of the thing we're looking for.