Skip to content

Commit bfc4970

Browse files
authored
Unrolled build for #155250
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 #142517 (comment)). 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.
2 parents d4f7856 + a6ec294 commit bfc4970

1 file changed

Lines changed: 23 additions & 6 deletions

File tree

library/std/src/sys/process/windows/child_pipe.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
22
use crate::ops::Neg;
33
use crate::os::windows::prelude::*;
4+
use crate::sync::atomic::Atomic;
5+
use crate::sync::atomic::Ordering::Relaxed;
46
use crate::sys::handle::Handle;
57
use crate::sys::{FromInner, IntoInner, api, c};
68
use crate::{mem, ptr};
@@ -70,10 +72,19 @@ pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) ->
7072
let mut object_attributes = c::OBJECT_ATTRIBUTES::default();
7173
object_attributes.Length = size_of::<c::OBJECT_ATTRIBUTES>() as u32;
7274

73-
// Open a handle to the pipe filesystem (`\??\PIPE\`).
74-
// This will be used when creating a new annon pipe.
75-
let pipe_fs = {
76-
let path = api::unicode_str!(r"\??\PIPE\");
75+
// Open a handle to the pipe filesystem (`\Device\NamedPipe\`).
76+
// This will be used when creating a new anonymous pipe.
77+
//
78+
// We cache the handle once so we can reuse it without needing to reopen it each time.
79+
// NOTE: this means the handle may appear to be leaked but that's fine because
80+
// it's only one handle and the OS will clean it up when the process exits.
81+
static PIPE_FS: Atomic<c::HANDLE> = Atomic::<c::HANDLE>::new(ptr::null_mut());
82+
let pipe_fs = if let handle = PIPE_FS.load(Relaxed)
83+
&& !handle.is_null()
84+
{
85+
handle
86+
} else {
87+
let path = api::unicode_str!(r"\Device\NamedPipe\");
7788
object_attributes.ObjectName = path.as_ptr();
7889
let mut pipe_fs = ptr::null_mut();
7990
let status = c::NtOpenFile(
@@ -85,7 +96,13 @@ pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) ->
8596
c::FILE_SYNCHRONOUS_IO_NONALERT, // synchronous access
8697
);
8798
if c::nt_success(status) {
88-
Handle::from_raw_handle(pipe_fs)
99+
match PIPE_FS.compare_exchange(ptr::null_mut(), pipe_fs, Relaxed, Relaxed) {
100+
Ok(_) => pipe_fs,
101+
Err(existing) => {
102+
c::CloseHandle(pipe_fs);
103+
existing
104+
}
105+
}
89106
} else {
90107
return Err(io::Error::from_raw_os_error(c::RtlNtStatusToDosError(status) as i32));
91108
}
@@ -104,7 +121,7 @@ pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) ->
104121
let ours = {
105122
// Use the pipe filesystem as the root directory.
106123
// With no name provided, an anonymous pipe will be created.
107-
object_attributes.RootDirectory = pipe_fs.as_raw_handle();
124+
object_attributes.RootDirectory = pipe_fs;
108125

109126
// A negative timeout value is a relative time (rather than an absolute time).
110127
// The time is given in 100's of nanoseconds so this is 50 milliseconds.

0 commit comments

Comments
 (0)