Skip to content

Commit c9f67f5

Browse files
committed
Closing connections properly on Windows
The current closing logic was causing a deadlock becuase an unused pipe was being returned when the close was called on the listenering. This sets a flag so we can detect that we should not use that pipe connection which wasn't actually connected to a client but returned from the async call becuase we told it too. Signed-off-by: James Sturtevant <[email protected]>
1 parent 9d251f9 commit c9f67f5

File tree

1 file changed

+20
-20
lines changed

1 file changed

+20
-20
lines changed

src/sync/sys/windows/net.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,8 @@ impl PipeListener {
100100
trace!("listening for connection");
101101
let result = unsafe { ConnectNamedPipe(np.named_pipe, ol.as_mut_ptr())};
102102
if result != 0 {
103-
if self.shutting_down.load(Ordering::SeqCst) {
104-
np.close().unwrap_or_else(|err| trace!("Failed to close the pipe {:?}", err));
105-
return Err(io::Error::new(
106-
io::ErrorKind::Other,
107-
"closing pipe",
108-
));
103+
if let Some(error) = self.handle_shutdown(&np) {
104+
return Err(error);
109105
}
110106
return Err(io::Error::last_os_error());
111107
}
@@ -119,24 +115,16 @@ impl PipeListener {
119115
return Err(io::Error::last_os_error());
120116
}
121117
_ => {
122-
if self.shutting_down.load(Ordering::SeqCst) {
123-
np.close().unwrap_or_else(|err| trace!("Failed to close the pipe {:?}", err));
124-
return Err(io::Error::new(
125-
io::ErrorKind::Other,
126-
"closing pipe",
127-
));
118+
if let Some(shutdown_signal) = self.handle_shutdown(&np) {
119+
return Err(shutdown_signal);
128120
}
129121
Ok(Some(np))
130122
}
131123
}
132124
}
133125
e if e.raw_os_error() == Some(ERROR_PIPE_CONNECTED as i32) => {
134-
if self.shutting_down.load(Ordering::SeqCst) {
135-
np.close().unwrap_or_else(|err| trace!("Failed to close the pipe {:?}", err));
136-
return Err(io::Error::new(
137-
io::ErrorKind::Other,
138-
"closing pipe",
139-
));
126+
if let Some(error) = self.handle_shutdown(&np) {
127+
return Err(error);
140128
}
141129
Ok(Some(np))
142130
}
@@ -149,6 +137,17 @@ impl PipeListener {
149137
}
150138
}
151139

140+
fn handle_shutdown(&self, np: &PipeConnection) -> Option<io::Error> {
141+
if self.shutting_down.load(Ordering::SeqCst) {
142+
np.close().unwrap_or_else(|err| trace!("Failed to close the pipe {:?}", err));
143+
return Some(io::Error::new(
144+
io::ErrorKind::Other,
145+
"closing pipe",
146+
));
147+
}
148+
None
149+
}
150+
152151
fn new_instance(&self) -> io::Result<isize> {
153152
let name = OsStr::new(&self.address.as_str())
154153
.encode_wide()
@@ -386,7 +385,8 @@ mod test {
386385

387386
#[test]
388387
fn should_accept_new_client() {
389-
let listener = Arc::new(PipeListener::new(r"\\.\pipe\ttrpc-test-accept").unwrap());
388+
let address = r"\\.\pipe\ttrpc-test-accept";
389+
let listener = Arc::new(PipeListener::new(address).unwrap());
390390

391391
let listener_server = listener.clone();
392392
let thread = std::thread::spawn(move || {
@@ -404,7 +404,7 @@ mod test {
404404
}
405405
});
406406

407-
wait_socket_working(r"\\.\pipe\ttrpc-test-accept", 10, 5).unwrap();
407+
wait_socket_working(address, 10, 5).unwrap();
408408
thread.join().unwrap();
409409
}
410410

0 commit comments

Comments
 (0)