issue #131: disable non-blocking IO during UNIX accept()
accept() (per interface) returns a non-blocking socket because the listener socket is in non-blocking mode, therefore it is pure scheduling luck that a connecting-in child has a chance to write anything for the top-level processs to read during the subsequent .recv(). A higher forks setting in ansible.cfg was enough to cause our luck to run out, causing the .recv() to crashi with EGAIN, and the multiplexer to respond to the handler's crash by calling its disconnect method. This is why some reports mentioned ECONNREFUSED -- the listener really was gone, because its Stream class had crashed. Meanwhile since the window where we're waiting for the remote process to identify itself is tiny, simply flip off O_NONBLOCK for the duration of the connection handshake. Stream.accept() (via Side.__init__) will reenable O_NONBLOCK for the descriptors it duplicates, so we don't even need to bother turning this back off. A better solution entails splitting Stream up into a state machine and doing the handshake with non-blocking IO, but that isn't going to be available until asynchronous connect is implemented. Meanwhile in reality this solution is probably 100% fine.
Showing
Please register or sign in to comment