Skip to content

Commit

Permalink
Windows: Fallback for overlapped I/O
Browse files Browse the repository at this point in the history
Try waiting on the file handle once. If that fails then give up.
  • Loading branch information
ChrisDenton committed Jul 6, 2022
1 parent ae60dbd commit 3ae47e7
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 1 deletion.
14 changes: 13 additions & 1 deletion library/std/src/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,9 @@ union IO_STATUS_BLOCK_union {
}
impl Default for IO_STATUS_BLOCK_union {
fn default() -> Self {
Self { Pointer: ptr::null_mut() }
let mut this = Self { Pointer: ptr::null_mut() };
this.Status = STATUS_PENDING;
this
}
}
#[repr(C)]
Expand All @@ -335,6 +337,16 @@ pub struct IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_union,
pub Information: usize,
}
impl IO_STATUS_BLOCK {
pub fn status(&self) -> NTSTATUS {
// SAFETY: If `self.u.Status` was set then this is obviously safe.
// If `self.u.Pointer` was set then this is the equivalent to converting
// the pointer to an integer, which is also safe.
// Currently the only safe way to construct `IO_STATUS_BLOCK` outside of
// this module is to call the `default` method, which sets the `Status`.
unsafe { self.u.Status }
}
}

pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn(
dwErrorCode: DWORD,
Expand Down
13 changes: 13 additions & 0 deletions library/std/src/sys/windows/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ impl Handle {
offset.map(|n| n as _).as_ref(),
None,
);

let status = if status == c::STATUS_PENDING {
c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE);
io_status.status()
} else {
status
};
match status {
// If the operation has not completed then abort the process.
// Doing otherwise means that the buffer and stack may be written to
Expand Down Expand Up @@ -291,6 +298,12 @@ impl Handle {
None,
)
};
let status = if status == c::STATUS_PENDING {
unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
io_status.status()
} else {
status
};
match status {
// If the operation has not completed then abort the process.
// Doing otherwise means that the buffer may be read and the stack
Expand Down

0 comments on commit 3ae47e7

Please sign in to comment.