Skip to content

Conversation

klu-dev
Copy link

@klu-dev klu-dev commented Aug 17, 2025

Closes #97

This is an implementation to support Windows file handle overlapped I/O. The basic idea is:

  1. Add an File struct in PacketInner. The File struct have read and write OVERLAPPED struct. The read and write struct address will exposed to callers. The caller use read and write overlapped pointer as parameter for ReadFile/WriteFile operation.
  2. IOCP completion events receive read and write address which will be converted back to Packet for updating events
  3. New PollerIocpFileExt trait which has add_file and remove_file API to extend file functionality.

@klu-dev klu-dev force-pushed the kail/windows_file branch 5 times, most recently from d0cf4d3 to 5e24b6b Compare August 17, 2025 14:10
@notgull notgull self-requested a review August 17, 2025 15:51
@klu-dev klu-dev force-pushed the kail/windows_file branch from 5e24b6b to d60ff79 Compare August 18, 2025 12:22
Copy link
Member

@notgull notgull left a comment

Choose a reason for hiding this comment

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

Thank you! I imagine this was a significant effort. I appreciate you writing this. However, I definitely need to read through this and understand this. So this review may take some time.

The immediate thing that jumps out at me is the weird pointer offsets in the FileOverlapped traits. This seems fragile to me. I would prefer them to be direct pointers; I think that would be better when it comes to strict provenance.

Also, have you run this code under Miri on Windows?

@klu-dev
Copy link
Author

klu-dev commented Aug 26, 2025

Hi @notgull

Thanks for reviewing. FileCompletionHandle trait would provide conversion from overlapped pointer to packet which will depends on FileOverlapped trait providing pointer offset to packet. Maybe should rename FileOverlapped to FileOverlappedOffset.

I do not run the code with miri. Currently I am writing NamedPipe code in async_io crate. I found the code need some change in order for better integration with async_io. I also found a problem that is IOCP port still can receive event after the file handle is removed from the poller and file handle is closed as long as there is I/O operation with overlapped pointer. But the packet has been dropped at this time. This will cause memory access violation

I will request review after the issue is fixed. I will also run code in miri and solve your comments.

@klu-dev
Copy link
Author

klu-dev commented Sep 19, 2025

Hi @notgull

I have updated the code to solve IocpFilePacket returned by add_file lifetime issue. The idea is IocpFilePacket will increase reference count of Packet, so the Pakcet is still valid when the Poller is dropped. And for every success overlapped I/O operation ((the operation return TRUE or ERROR_IO_PENDING) will also add reference count, the reference count will decrease after the IOCP event is received. This will make sure the IOCP returned overlapped pointer still valid even the packet is remove from the poller and IocpFilePacket is dropped. I also update the code according your previous comments.

I implmeneted NamedPipe in async-io according the updated polling code. The test code is https://github.com/klu-dev/async-io/blob/kail/windows_named_pipe/tests/windows_named_pipe.rs . The main function has completed. I am thinking adding MESSAGE mode and configurable parameter when create named pipe.

I try to run miri, but get the following error. Miri do not support code calling native OS API. So the code add an IocpFilePacket::test_ref_count method used in test case to check Packet Arc count.

test writable_after_register ... error: unsupported operation: CreateFileW: Unsupported flags_and_attributes: 1073741824
--> C:\Users\tom_k.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\fs\windows.rs:334:13
|
334 | / c::CreateFileW(
335 | | path.as_ptr(),
336 | | opts.get_access_mode()?,
337 | | opts.share_mode,
... |
341 | | ptr::null_mut(),
342 | | )
| |_____________^ unsupported operation occurred here
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
= note: BACKTRACE on thread writable_after_register:
= note: inside std::sys::fs::windows::File::open_native at C:\Users\tom_k.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\fs\windows.rs:334:13: 342:14
= note: inside std::sys::fs::windows::File::open at C:\Users\tom_k.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\fs\windows.rs:323:9: 323:39
= note: inside std::fs::OpenOptions::_open at C:\Users\tom_k.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\fs.rs:1721:9: 1721:42
= note: inside std::fs::OpenOptions::open::<&str> at C:\Users\tom_k.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\fs.rs:1717:9: 1717:34
note: inside client
--> tests\windows_overlapped.rs:197:16
|
197 | let file = opts.open(name)?;
| ^^^^^^^^^^^^^^^
note: inside writable_after_register
--> tests\windows_overlapped.rs:216:22
|
216 | let client = client(&name);
| ^^^^^^^^^^^^^
note: inside closure
--> tests\windows_overlapped.rs:213:29

@klu-dev klu-dev force-pushed the kail/windows_file branch 2 times, most recently from 24eb900 to 550d1eb Compare September 19, 2025 17:07
@notgull
Copy link
Member

notgull commented Sep 20, 2025

Noting that I've seen this patch, I'm doing research to ensure everything is sound.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Support overlapped operations in Windows

2 participants