Looking at the current implementation, if a SessionExpiredException was thrown, then the expired event is enqueued, as is the event-of-death for the event thread; and isAlive() is false. So, as indicated by Camille, your patch doesn't appear to have the affect you expect.
As for the race conditions. A call to close() will put the client in the closing mode, but the state may end up being CLOSED, CONNECTING or CONNECTED as the send thread doesn't enforce strict state transitions. The client will close, but state.isAlive() may still return true after the send thread has died. Note that this isn't easy to test, but you can step through it with a debugger to see how CLOSED can easily be stomped by CONNECTING (especially with the random sleep happening after a test for closing when isFirstConnect is false).
Another, rather exotic case (hopefully doesn't ever happen), is when a Throwable isn't caught, e.g. an error that is not an Exception.
In any case, I'm still not sure whether a dying send-thread should indicate the session has expired. I looked at the state diagram, but it seems to conflict with what I see in the code.