THRIFT-5909: Fixed '#to_io gives NilClass' error #3266
Merged
+3
−1
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.

In a race condition in Thrift::NonblockingServer, the following sequence could occur:
This patch changes Thrift::ServerSocket#to_io to raise IOError if @handle is nil, which is the expected behavior for closed streams in Ruby:
Before the change
sequenceDiagram participant T1 as Thread 1<br/>(NonblockingServer serve) participant T2 as Thread 2<br/>(server.shutdown) participant T3 as Thread 3<br/>(shutdown helper) participant S as ServerTransport<br/>(@server_transport) T1->>S: listen activate S loop accept socket Note over T1: 1. Check if server transport is closed T1->>S: closed? S-->>T1: returns false Note over T2: 2. Server is asked to shut down, spawns helper thread activate T2 T2->>T3: &shutdown_proc deactivate T2 activate T3 Note over T3: 3. Closes server transport T3->>S: close() S->>S: @handle = nil deactivate T3 deactivate S Note over T1: 4. Back in serve loop<br/>select([@server_transport], nil, nil, 0.1) T1->>S: @server_transport.to_io<br/>(@handle is now nil) S-->>T1: returns nil Note over T1: 5. IO.select throws an error T1-->>T1: TypeError:<br/>"can't convert<br/>SpecServerSocket to IO<br/>(to_io gives NilClass)" endAfter the change
sequenceDiagram participant T1 as Thread 1<br/>(NonblockingServer serve) participant T2 as Thread 2<br/>(server.shutdown) participant T3 as Thread 3<br/>(shutdown helper) participant S as ServerTransport<br/>(@server_transport) T1->>S: listen activate S loop accept socket Note over T1: 1. Check if server transport is closed T1->>S: closed? S-->>T1: returns false Note over T2: 2. Server is asked to shut down, spawns helper thread activate T2 T2->>T3: &shutdown_proc deactivate T2 activate T3 Note over T3: 3. Closes server transport T3->>S: close() S->>S: @handle = nil deactivate T3 deactivate S Note over T1: 4. Back in serve loop<br/>select([@server_transport], nil, nil, 0.1) T1->>S: @server_transport.to_io<br/>(@handle is now nil) S-->>T1: throws IOError nil end Note over T1: 5. rescues IOError T1->>T1: shutting down[skip ci]anywhere in the commit message to free up build resources.