A race in how Xserver handles clients connecting and disconnecting
I believe the way Xserver handles clients connecting and disconnecting contains a race which causes some clients to be dropped. The relevant code is in function CloseDownClient, in dix/dispatch.c lines 3466..3478:
Xserver counts the number of active clients in nClients variable, but only those clients which have completed initialization are accounted. Comment in lines 3466..3470 states that and, to the best of my knowledge, this comment accurately describes the behavior of Xserver. When the count reaches zero the whole server is marked for reset (lines 3477..3478). This causes function Dispatch to exit the main loop and call KillAllClients, which closes all connections. There are no checks if some clients are in the process of initialization. Those clients will have their sockets closed by server.
The following sequence of events will cause undesired behavior.
- Client 1 connects and gains status ClientStateInitial. nClients = 0.
- Client 1 performs initialization and gains status ClientStateRunning. nClients = 1.
- Client 2 connects and gains status ClientStateInitial. nClients = 1.
- Client 1 disconnects and gains status ClientStateGone. nClients = 0.
- Server resets because nClients = 0.
- Client 2 has its connection unexpectedly closed by remote side and receives SIGPIPE, POLLHUP or equivalent.