A wild guess is that some code for connection Z (which predates A and B)
holds a stale descriptor value and is closing it. This is a common bug in
application code. Easiest way to avoid it is to never pass file descriptors
as values--except to low-level routines--but as references (say, as a member
of another object). When the descriptor is closed, set the descriptor value
to -1 so that there's no loaded gun lying around. It's the same concept as
setting a pointer to NULL after calling free. Technically it's not needed
but it pays divdends when trying to track down bugs.
An even wilder guess is that you have a pending callback which is firing
after some other callback which closed the descriptor, resulting in the
previous guess scenario. Juggling multiple concurrent callbacks for the same
resource can be difficult and is best avoided if possible.