Handle fd reuse during epoll callback processing

There is a comment to this effect, but file descriptors can get reused.
If a read event and write event were triggered for a fd and the read
callback unregistered the fd (because the remote closed) and then
attempted a reconnect and the fd was reused when registerd, the write
callback was still getting invoked in the same iteration of event
handling. However, the callback wasn't intended for a disconnected
socket.

The bug was observed when attempting to reconnect dropped SSL
connections in a try/except block. It was causing the event hub
to freeze up indefinitely.

The event hub now tracks an ID for file descriptors and checks that the
ID at the start of even processing for a fd is the same after doing read
callback handling. If the ID changes the write callback is not invoked.