Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Fix windows socket
  • Loading branch information
youknowone committed Dec 12, 2025
commit d5fb695e5a7727b7fd7c7bfe9072decb06fbae89
2 changes: 0 additions & 2 deletions Lib/test/test_selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,6 @@ def test_unregister_after_fd_close_and_reuse(self):
s.unregister(r)
s.unregister(w)

# TODO: RUSTPYTHON
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON")
def test_unregister_after_socket_close(self):
s = self.SELECTOR()
self.addCleanup(s.close)
Expand Down
5 changes: 0 additions & 5 deletions Lib/test/test_socketserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,11 @@ def dgram_examine(self, proto, addr):
buf += data
self.assertEqual(buf, TEST_STR)

@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AssertionError: -1 != 18446744073709551615")
def test_TCPServer(self):
self.run_server(socketserver.TCPServer,
socketserver.StreamRequestHandler,
self.stream_examine)

@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AssertionError: -1 != 18446744073709551615")
def test_ThreadingTCPServer(self):
self.run_server(socketserver.ThreadingTCPServer,
socketserver.StreamRequestHandler,
Expand Down Expand Up @@ -217,13 +215,11 @@ def test_ForkingUnixStreamServer(self):
socketserver.StreamRequestHandler,
self.stream_examine)

@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AssertionError: -1 != 18446744073709551615")
def test_UDPServer(self):
self.run_server(socketserver.UDPServer,
socketserver.DatagramRequestHandler,
self.dgram_examine)

@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AssertionError: -1 != 18446744073709551615")
def test_ThreadingUDPServer(self):
self.run_server(socketserver.ThreadingUDPServer,
socketserver.DatagramRequestHandler,
Expand Down Expand Up @@ -298,7 +294,6 @@ def test_tcpserver_bind_leak(self):
socketserver.TCPServer((HOST, -1),
socketserver.StreamRequestHandler)

@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AssertionError: -1 != 18446744073709551615")
def test_context_manager(self):
with socketserver.TCPServer((HOST, 0),
socketserver.StreamRequestHandler) as server:
Expand Down
15 changes: 7 additions & 8 deletions crates/stdlib/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1065,8 +1065,7 @@ mod _socket {
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
Ok(format!(
"<socket object, fd={}, family={}, type={}, proto={}>",
// cast because INVALID_SOCKET is unsigned, so would show usize::MAX instead of -1
zelf.fileno() as i64,
zelf.fileno(),
zelf.family.load(),
zelf.kind.load(),
zelf.proto.load(),
Expand Down Expand Up @@ -1462,25 +1461,25 @@ mod _socket {
#[pymethod]
fn close(&self) -> io::Result<()> {
let sock = self.detach();
if sock != INVALID_SOCKET {
close_inner(sock)?;
if sock != INVALID_SOCKET as i64 {
close_inner(sock as RawSocket)?;
}
Ok(())
}

#[pymethod]
#[inline]
fn detach(&self) -> RawSocket {
fn detach(&self) -> i64 {
let sock = self.sock.write().take();
sock.map_or(INVALID_SOCKET, into_sock_fileno)
sock.map_or(INVALID_SOCKET as i64, |s| into_sock_fileno(s) as i64)
}
Comment on lines +1472 to 1475
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

rg -n --type rust '\.detach\s*\(' -B 3 -A 3

Repository: RustPython/RustPython

Length of output: 508


🏁 Script executed:

rg -n 'fn detach' crates/stdlib/src/socket.rs -B 2 -A 5

Repository: RustPython/RustPython

Length of output: 335


🏁 Script executed:

rg -n 'into_sock_fileno|close_inner' crates/stdlib/src/socket.rs -B 2 -A 5

Repository: RustPython/RustPython

Length of output: 1943


🏁 Script executed:

rg -n 'fn fileno' crates/stdlib/src/socket.rs -B 2 -A 5

Repository: RustPython/RustPython

Length of output: 315


🏁 Script executed:

rg -n 'INVALID_SOCKET|cfg.*windows' crates/stdlib/src/socket.rs | head -40

Repository: RustPython/RustPython

Length of output: 1563


🏁 Script executed:

sed -n '2374,2385p' crates/stdlib/src/socket.rs

Repository: RustPython/RustPython

Length of output: 333


🏁 Script executed:

rg -n 'RawSocket' crates/stdlib/src/socket.rs | grep -E 'type|cfg' | head -20

Repository: RustPython/RustPython

Length of output: 171


🏁 Script executed:

# Check if there are any comments or TODOs about Windows socket limitations
rg -n 'TODO|FIXME|BUG|XXX|HACK' crates/stdlib/src/socket.rs | grep -i 'socket\|window\|handle\|fd'

Repository: RustPython/RustPython

Length of output: 47


Verify the return type change impact across the codebase.

The detach() method now returns i64 instead of RawSocket. This is a breaking API change affecting:

  1. The close() method (line 1463), which has been properly updated to handle i64 and cast back to RawSocket for close_inner()
  2. Python code calling detach(), which receives i64 (Python's int safely represents this range)

On Windows, casting RawSocket (which is usize) to i64 can theoretically overflow if a socket handle exceeds i64::MAX. This same issue also affects the fileno() method (line 1482), suggesting it may be an accepted limitation of the current design. Consider documenting whether this is a known limitation or requires a fix.


#[pymethod]
fn fileno(&self) -> RawSocket {
fn fileno(&self) -> i64 {
self.sock
.read()
.as_ref()
.map_or(INVALID_SOCKET, sock_fileno)
.map_or(INVALID_SOCKET as i64, |s| sock_fileno(s) as i64)
}

#[pymethod]
Expand Down
Loading