(args: SetWakeupFdArgs, vm: &VirtualMachine)
| 364 | |
| 365 | #[pyfunction] |
| 366 | fn set_wakeup_fd(args: SetWakeupFdArgs, vm: &VirtualMachine) -> PyResult<i64> { |
| 367 | // TODO: implement warn_on_full_buffer |
| 368 | let _ = args.warn_on_full_buffer; |
| 369 | #[cfg(windows)] |
| 370 | let fd = args.fd.0; |
| 371 | #[cfg(not(windows))] |
| 372 | let fd = args.fd; |
| 373 | |
| 374 | if !vm.is_main_thread() { |
| 375 | return Err(vm.new_value_error("set_wakeup_fd only works in main thread")); |
| 376 | } |
| 377 | |
| 378 | #[cfg(windows)] |
| 379 | let is_socket = if fd != INVALID_WAKEUP { |
| 380 | use windows_sys::Win32::Networking::WinSock; |
| 381 | |
| 382 | crate::windows::init_winsock(); |
| 383 | let mut res = 0i32; |
| 384 | let mut res_size = core::mem::size_of::<i32>() as i32; |
| 385 | let res = unsafe { |
| 386 | WinSock::getsockopt( |
| 387 | fd, |
| 388 | WinSock::SOL_SOCKET, |
| 389 | WinSock::SO_ERROR, |
| 390 | &mut res as *mut i32 as *mut _, |
| 391 | &mut res_size, |
| 392 | ) |
| 393 | }; |
| 394 | // if getsockopt succeeded, fd is for sure a socket |
| 395 | let is_socket = res == 0; |
| 396 | if !is_socket { |
| 397 | let err = std::io::Error::last_os_error(); |
| 398 | // if getsockopt failed for some other reason, throw |
| 399 | if err.raw_os_error() != Some(WinSock::WSAENOTSOCK) { |
| 400 | return Err(err.into_pyexception(vm)); |
| 401 | } |
| 402 | // Validate that fd is a valid file descriptor using fstat |
| 403 | // First check if SOCKET can be safely cast to i32 (file descriptor) |
| 404 | let fd_i32 = i32::try_from(fd).map_err(|_| vm.new_value_error("invalid fd"))?; |
| 405 | // Verify the fd is valid by trying to fstat it |
| 406 | let borrowed_fd = |
| 407 | unsafe { crate::common::crt_fd::Borrowed::try_borrow_raw(fd_i32) } |
| 408 | .map_err(|e| e.into_pyexception(vm))?; |
| 409 | crate::common::fileutils::fstat(borrowed_fd).map_err(|e| e.into_pyexception(vm))?; |
| 410 | } |
| 411 | is_socket |
| 412 | } else { |
| 413 | false |
| 414 | }; |
| 415 | #[cfg(unix)] |
| 416 | if let Ok(fd) = unsafe { crate::common::crt_fd::Borrowed::try_borrow_raw(fd) } { |
| 417 | use nix::fcntl; |
| 418 | let oflags = fcntl::fcntl(fd, fcntl::F_GETFL).map_err(|e| e.into_pyexception(vm))?; |
| 419 | let nonblock = |
| 420 | fcntl::OFlag::from_bits_truncate(oflags).contains(fcntl::OFlag::O_NONBLOCK); |
| 421 | if !nonblock { |
| 422 | return Err(vm.new_value_error(format!( |
| 423 | "the fd {} must be in non-blocking mode", |
nothing calls this directly
no test coverage detected