mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #155250 - ChrisDenton:pipe-fs, r=Mark-Simulacrum
Windows: Cache the pipe filesystem handle Updates the anonymous pipe handling based on feedback from @lhecker (see https://github.com/rust-lang/rust/pull/142517#discussion_r3065864262). This does two things: 1. Cache the handle to the pipe filesystem so we don't have to reopen it each time. 2. Use the `\Device\NamedPipe\` directly instead of the symlink to it.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::ops::Neg;
|
||||
use crate::os::windows::prelude::*;
|
||||
use crate::sync::atomic::Atomic;
|
||||
use crate::sync::atomic::Ordering::Relaxed;
|
||||
use crate::sys::handle::Handle;
|
||||
use crate::sys::{FromInner, IntoInner, api, c};
|
||||
use crate::{mem, ptr};
|
||||
@@ -70,10 +72,19 @@ pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) ->
|
||||
let mut object_attributes = c::OBJECT_ATTRIBUTES::default();
|
||||
object_attributes.Length = size_of::<c::OBJECT_ATTRIBUTES>() as u32;
|
||||
|
||||
// Open a handle to the pipe filesystem (`\??\PIPE\`).
|
||||
// This will be used when creating a new annon pipe.
|
||||
let pipe_fs = {
|
||||
let path = api::unicode_str!(r"\??\PIPE\");
|
||||
// Open a handle to the pipe filesystem (`\Device\NamedPipe\`).
|
||||
// This will be used when creating a new anonymous pipe.
|
||||
//
|
||||
// We cache the handle once so we can reuse it without needing to reopen it each time.
|
||||
// NOTE: this means the handle may appear to be leaked but that's fine because
|
||||
// it's only one handle and the OS will clean it up when the process exits.
|
||||
static PIPE_FS: Atomic<c::HANDLE> = Atomic::<c::HANDLE>::new(ptr::null_mut());
|
||||
let pipe_fs = if let handle = PIPE_FS.load(Relaxed)
|
||||
&& !handle.is_null()
|
||||
{
|
||||
handle
|
||||
} else {
|
||||
let path = api::unicode_str!(r"\Device\NamedPipe\");
|
||||
object_attributes.ObjectName = path.as_ptr();
|
||||
let mut pipe_fs = ptr::null_mut();
|
||||
let status = c::NtOpenFile(
|
||||
@@ -85,7 +96,13 @@ pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) ->
|
||||
c::FILE_SYNCHRONOUS_IO_NONALERT, // synchronous access
|
||||
);
|
||||
if c::nt_success(status) {
|
||||
Handle::from_raw_handle(pipe_fs)
|
||||
match PIPE_FS.compare_exchange(ptr::null_mut(), pipe_fs, Relaxed, Relaxed) {
|
||||
Ok(_) => pipe_fs,
|
||||
Err(existing) => {
|
||||
c::CloseHandle(pipe_fs);
|
||||
existing
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(io::Error::from_raw_os_error(c::RtlNtStatusToDosError(status) as i32));
|
||||
}
|
||||
@@ -104,7 +121,7 @@ pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) ->
|
||||
let ours = {
|
||||
// Use the pipe filesystem as the root directory.
|
||||
// With no name provided, an anonymous pipe will be created.
|
||||
object_attributes.RootDirectory = pipe_fs.as_raw_handle();
|
||||
object_attributes.RootDirectory = pipe_fs;
|
||||
|
||||
// A negative timeout value is a relative time (rather than an absolute time).
|
||||
// The time is given in 100's of nanoseconds so this is 50 milliseconds.
|
||||
|
||||
Reference in New Issue
Block a user