1 /* fhandler_pipe.cc: pipes for Cygwin.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 #include <sys/socket.h>
19 #include "shared_info.h"
23 /* This is only to be used for writing. When reading,
24 STATUS_PIPE_EMPTY simply means there's no data to be read. */
25 #define STATUS_PIPE_IS_CLOSED(status) \
26 ({ NTSTATUS _s = (status); \
27 _s == STATUS_PIPE_CLOSING \
28 || _s == STATUS_PIPE_BROKEN \
29 || _s == STATUS_PIPE_EMPTY; })
31 fhandler_pipe_fifo::fhandler_pipe_fifo ()
32 : fhandler_base (), pipe_buf_size (DEFAULT_PIPEBUFSIZE
)
37 fhandler_pipe::fhandler_pipe ()
38 : fhandler_pipe_fifo (), popen_pid (0)
40 need_fork_fixup (true);
43 /* The following function is intended for fhandler_pipe objects
44 created by the second version of fhandler_pipe::create below. See
45 the comment preceding the latter.
47 In addition to setting the blocking mode of the pipe handle, it
48 also sets the pipe's read mode to byte_stream unconditionally. */
50 fhandler_pipe::set_pipe_non_blocking (bool nonblocking
)
54 FILE_PIPE_INFORMATION fpi
;
56 fpi
.ReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
57 fpi
.CompletionMode
= nonblocking
? FILE_PIPE_COMPLETE_OPERATION
58 : FILE_PIPE_QUEUE_OPERATION
;
59 status
= NtSetInformationFile (get_handle (), &io
, &fpi
, sizeof fpi
,
61 if (!NT_SUCCESS (status
))
62 debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status
);
66 fhandler_pipe::init (HANDLE f
, DWORD a
, mode_t mode
, int64_t uniq_id
)
68 /* FIXME: Have to clean this up someday
69 FIXME: Do we have to check for both !get_win32_name() and
70 !*get_win32_name()? */
71 if ((!get_win32_name () || !*get_win32_name ()) && get_name ())
75 char *hold_normalized_name
= (char *) alloca (strlen (get_name ()) + 1);
76 for (s
= get_name (), d
= hold_normalized_name
; *s
; s
++, d
++)
82 set_name (hold_normalized_name
);
85 bool opened_properly
= a
& FILE_CREATE_PIPE_INSTANCE
;
86 a
&= ~FILE_CREATE_PIPE_INSTANCE
;
87 fhandler_base::init (f
, a
, mode
);
88 close_on_exec (mode
& O_CLOEXEC
);
90 set_unique_id (uniq_id
| !!(mode
& GENERIC_WRITE
));
92 /* Set read pipe always nonblocking to allow signal handling
93 even with FILE_SYNCHRONOUS_IO_NONALERT. */
94 set_pipe_non_blocking (get_device () == FH_PIPER
?
95 true : is_nonblocking ());
99 extern "C" int sscanf (const char *, const char *, ...);
102 fhandler_pipe::open (int flags
, mode_t mode
)
104 HANDLE proc
, nio_hdl
= NULL
;
106 fhandler_pipe
*fh
= NULL
, *fhr
= NULL
, *fhw
= NULL
;
108 int pid
, rwflags
= (flags
& O_ACCMODE
);
110 bool got_one
= false;
112 if (sscanf (get_name (), "/proc/%d/fd/pipe:[%llu]",
113 &pid
, (long long *) &uniq_id
) < 2)
118 if (pid
== myself
->pid
)
120 cygheap_fdenum
cfd (true);
121 while (cfd
.next () >= 0)
123 /* Windows doesn't allow to copy a pipe HANDLE with another access
124 mode. So we check for read and write side of pipe and try to
125 find the one matching the requested access mode. */
126 if (cfd
->get_unique_id () == uniq_id
)
128 else if (cfd
->get_unique_id () == uniq_id
+ 1)
132 if ((rwflags
== O_RDONLY
&& !(cfd
->get_access () & GENERIC_READ
))
133 || (rwflags
== O_WRONLY
&& !(cfd
->get_access () & GENERIC_WRITE
)))
137 pc
.close_conv_handle ();
138 if (!cfd
->dup (this, flags
))
142 /* Found the pipe but access mode didn't match? EACCES.
144 set_errno (got_one
? EACCES
: ENOENT
);
154 if (!(proc
= OpenProcess (PROCESS_DUP_HANDLE
, false, p
->dwProcessId
)))
159 fhr
= p
->pipe_fhandler (uniq_id
, size
);
160 if (fhr
&& rwflags
== O_RDONLY
)
164 fhw
= p
->pipe_fhandler (uniq_id
+ 1, size
);
165 if (fhw
&& rwflags
== O_WRONLY
)
170 /* Too bad, but Windows only allows the same access mode when dup'ing
172 set_errno (fhr
|| fhw
? EACCES
: ENOENT
);
175 inh
= !(flags
& O_CLOEXEC
);
176 if (!DuplicateHandle (proc
, fh
->get_handle (), GetCurrentProcess (),
177 &nio_hdl
, 0, inh
, DUPLICATE_SAME_ACCESS
))
182 init (nio_hdl
, fh
->get_access (), mode
& O_TEXT
?: O_BINARY
,
183 fh
->get_plain_ino ());
189 CloseHandle (nio_hdl
);
198 fhandler_pipe::open_setup (int flags
)
200 bool read_mtx_created
= false;
202 if (!fhandler_base::open_setup (flags
))
204 if (get_dev () == FH_PIPER
&& !read_mtx
)
206 SECURITY_ATTRIBUTES
*sa
= sec_none_cloexec (flags
);
207 read_mtx
= CreateMutex (sa
, FALSE
, NULL
);
209 read_mtx_created
= true;
212 debug_printf ("CreateMutex read_mtx failed: %E");
218 SECURITY_ATTRIBUTES
*sa
= sec_none_cloexec (flags
);
219 hdl_cnt_mtx
= CreateMutex (sa
, FALSE
, NULL
);
222 debug_printf ("CreateMutex hdl_cnt_mtx failed: %E");
223 goto err_close_read_mtx
;
229 if (read_mtx_created
)
230 CloseHandle (read_mtx
);
236 fhandler_pipe::lseek (off_t offset
, int whence
)
238 debug_printf ("(%D, %d)", offset
, whence
);
244 fhandler_pipe::fadvise (off_t offset
, off_t length
, int advice
)
250 fhandler_pipe::fallocate (int mode
, off_t offset
, off_t length
)
252 return (mode
& __FALLOC_FL_TRUNCATE
) ? EINVAL
: ESPIPE
;
256 fhandler_pipe::get_proc_fd_name (char *buf
)
258 __small_sprintf (buf
, "pipe:[%U]", get_plain_ino ());
263 fhandler_pipe::release_select_sem (const char *from
)
266 if (get_dev () == FH_PIPER
) /* Number of select() and writer */
267 n_release
= get_obj_handle_count (select_sem
)
268 - get_obj_handle_count (read_mtx
);
269 else /* Number of select() call and reader */
270 n_release
= get_obj_handle_count (select_sem
)
271 - get_obj_handle_count (get_handle ());
272 debug_printf("%s(%s) release %d", from
,
273 get_dev () == FH_PIPER
? "PIPER" : "PIPEW", n_release
);
275 ReleaseSemaphore (select_sem
, n_release
, NULL
);
279 fhandler_pipe::raw_read (void *ptr
, size_t& len
)
282 NTSTATUS status
= STATUS_SUCCESS
;
284 ULONGLONG t0
= GetTickCount64 (); /* Init timer */
285 const ULONGLONG t0_threshold
= 20;
290 DWORD timeout
= is_nonblocking () ? 0 : INFINITE
;
291 DWORD waitret
= cygwait (read_mtx
, timeout
);
305 pthread::static_cancel_self ();
308 /* Should not reach here. */
315 ULONG_PTR nbytes_now
= 0;
316 ULONG len1
= (ULONG
) (len
- nbytes
);
317 DWORD select_sem_timeout
= 0;
319 FILE_PIPE_LOCAL_INFORMATION fpli
;
320 status
= NtQueryInformationFile (get_handle (), &io
,
321 &fpli
, sizeof (fpli
),
322 FilePipeLocalInformation
);
323 if (NT_SUCCESS (status
))
325 if (fpli
.ReadDataAvailable
== 0 && nbytes
!= 0)
328 else if (nbytes
!= 0)
330 status
= NtReadFile (get_handle (), NULL
, NULL
, NULL
, &io
, ptr
,
332 if (isclosed ()) /* A signal handler might have closed the fd. */
335 nbytes
= (size_t) -1;
337 else if (NT_SUCCESS (status
) || status
== STATUS_BUFFER_OVERFLOW
)
339 nbytes_now
= io
.Information
;
340 ptr
= ((char *) ptr
) + nbytes_now
;
341 nbytes
+= nbytes_now
;
342 if (select_sem
&& nbytes_now
> 0)
343 release_select_sem ("raw_read");
347 /* Some errors are not really errors. Detect such cases here. */
350 case STATUS_END_OF_FILE
:
351 case STATUS_PIPE_BROKEN
:
352 /* This is really EOF. */
354 case STATUS_PIPE_LISTENING
:
355 case STATUS_PIPE_EMPTY
:
358 if (is_nonblocking ())
361 nbytes
= (size_t) -1;
364 /* If the pipe is a non-cygwin pipe, select_sem trick
365 does not work. As a result, the following cygwait()
366 will return only after timeout occurs. This causes
367 performance degradation. However, setting timeout
368 to zero causes high CPU load. So, set timeout to
369 non-zero only when select_sem is valid or pipe is
370 not ready to read for more than t0_threshold.
371 This prevents both the performance degradation and
372 the high CPU load. */
373 if (select_sem
|| GetTickCount64 () - t0
> t0_threshold
)
374 select_sem_timeout
= 1;
375 waitret
= cygwait (select_sem
, select_sem_timeout
);
376 if (waitret
== WAIT_CANCELED
)
377 pthread::static_cancel_self ();
378 else if (waitret
== WAIT_SIGNALED
)
381 nbytes
= (size_t) -1;
386 __seterrno_from_nt_status (status
);
387 nbytes
= (size_t) -1;
392 if ((nbytes_now
== 0 && !NT_SUCCESS (status
))
393 || status
== STATUS_BUFFER_OVERFLOW
)
396 ReleaseMutex (read_mtx
);
401 fhandler_pipe::reader_closed ()
405 WaitForSingleObject (hdl_cnt_mtx
, INFINITE
);
406 int n_reader
= get_obj_handle_count (query_hdl
);
407 int n_writer
= get_obj_handle_count (get_handle ());
408 ReleaseMutex (hdl_cnt_mtx
);
409 return n_reader
== n_writer
;
413 fhandler_pipe_fifo::raw_write (const void *ptr
, size_t len
)
417 NTSTATUS status
= STATUS_SUCCESS
;
424 if (reader_closed ())
431 if (len
<= pipe_buf_size
|| pipe_buf_size
== 0)
433 else if (is_nonblocking ())
434 chunk
= len
= pipe_buf_size
;
436 chunk
= pipe_buf_size
;
438 if (!(evt
= CreateEvent (NULL
, false, false, NULL
)))
444 /* Write in chunks, accumulating a total. If there's an error, just
445 return the accumulated total unless the first write fails, in
446 which case return -1. */
449 ULONG_PTR nbytes_now
= 0;
450 size_t left
= len
- nbytes
;
452 DWORD waitret
= WAIT_OBJECT_0
;
458 /* NtWriteFile returns success with # of bytes written == 0 if writing
459 on a non-blocking pipe fails because the pipe buffer doesn't have
463 - A write request for {PIPE_BUF} or fewer bytes shall have the
464 following effect: if there is sufficient space available in the
465 pipe, write() shall transfer all the data and return the number
466 of bytes requested. Otherwise, write() shall transfer no data and
467 return -1 with errno set to [EAGAIN].
469 - A write request for more than {PIPE_BUF} bytes shall cause one
472 - When at least one byte can be written, transfer what it can and
473 return the number of bytes written. When all data previously
474 written to the pipe is read, it shall transfer at least {PIPE_BUF}
477 - When no data can be written, transfer no data, and return -1 with
478 errno set to [EAGAIN]. */
481 status
= NtWriteFile (get_handle (), evt
, NULL
, NULL
, &io
,
482 (PVOID
) ptr
, len1
, NULL
, NULL
);
483 if (status
== STATUS_PENDING
)
485 while (WAIT_TIMEOUT
==
486 (waitret
= cygwait (evt
, (DWORD
) 0, cw_cancel
| cw_sig
)))
488 if (reader_closed ())
490 CancelIo (get_handle ());
496 cygwait (select_sem
, 10);
498 /* If io.Status is STATUS_CANCELLED after CancelIo, IO has
499 actually been cancelled and io.Information contains the
500 number of bytes processed so far.
501 Otherwise IO has been finished regulary and io.Status
502 contains valid success or error information. */
503 CancelIo (get_handle ());
504 if (waitret
== WAIT_SIGNALED
&& io
.Status
!= STATUS_CANCELLED
)
505 waitret
= WAIT_OBJECT_0
;
507 if (waitret
== WAIT_CANCELED
)
508 status
= STATUS_THREAD_CANCELED
;
509 else if (waitret
== WAIT_SIGNALED
)
510 status
= STATUS_THREAD_SIGNALED
;
514 if (!is_nonblocking () || !NT_SUCCESS (status
) || io
.Information
> 0
519 if (isclosed ()) /* A signal handler might have closed the fd. */
521 if (waitret
== WAIT_OBJECT_0
)
526 else if (NT_SUCCESS (status
)
527 || status
== STATUS_THREAD_CANCELED
528 || status
== STATUS_THREAD_SIGNALED
)
530 nbytes_now
= io
.Information
;
531 ptr
= ((char *) ptr
) + nbytes_now
;
532 nbytes
+= nbytes_now
;
533 if (select_sem
&& nbytes_now
> 0)
534 release_select_sem ("raw_write");
535 /* 0 bytes returned? EAGAIN. See above. */
536 if (NT_SUCCESS (status
) && nbytes
== 0)
539 else if (STATUS_PIPE_IS_CLOSED (status
))
545 __seterrno_from_nt_status (status
);
552 if (status
== STATUS_THREAD_SIGNALED
&& nbytes
== 0)
554 else if (status
== STATUS_THREAD_CANCELED
)
555 pthread::static_cancel_self ();
560 fhandler_pipe::set_close_on_exec (bool val
)
562 fhandler_base::set_close_on_exec (val
);
564 set_no_inheritance (read_mtx
, val
);
566 set_no_inheritance (select_sem
, val
);
568 set_no_inheritance (query_hdl
, val
);
569 set_no_inheritance (hdl_cnt_mtx
, val
);
573 fhandler_pipe::fixup_after_fork (HANDLE parent
)
575 fork_fixup (parent
, hdl_cnt_mtx
, "hdl_cnt_mtx");
576 WaitForSingleObject (hdl_cnt_mtx
, INFINITE
);
578 fork_fixup (parent
, read_mtx
, "read_mtx");
580 fork_fixup (parent
, select_sem
, "select_sem");
582 fork_fixup (parent
, query_hdl
, "query_hdl");
583 if (query_hdl_close_req_evt
)
584 fork_fixup (parent
, query_hdl_close_req_evt
, "query_hdl_close_req_evt");
586 fhandler_base::fixup_after_fork (parent
);
587 ReleaseMutex (hdl_cnt_mtx
);
591 fhandler_pipe::dup (fhandler_base
*child
, int flags
)
593 fhandler_pipe
*ftp
= (fhandler_pipe
*) child
;
594 ftp
->set_popen_pid (0);
597 WaitForSingleObject (hdl_cnt_mtx
, INFINITE
);
598 if (fhandler_base::dup (child
, flags
))
601 !DuplicateHandle (GetCurrentProcess (), read_mtx
,
602 GetCurrentProcess (), &ftp
->read_mtx
,
603 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
609 else if (select_sem
&&
610 !DuplicateHandle (GetCurrentProcess (), select_sem
,
611 GetCurrentProcess (), &ftp
->select_sem
,
612 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
618 else if (query_hdl
&&
619 !DuplicateHandle (GetCurrentProcess (), query_hdl
,
620 GetCurrentProcess (), &ftp
->query_hdl
,
621 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
627 else if (!DuplicateHandle (GetCurrentProcess (), hdl_cnt_mtx
,
628 GetCurrentProcess (), &ftp
->hdl_cnt_mtx
,
629 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
635 else if (query_hdl_close_req_evt
&&
636 !DuplicateHandle (GetCurrentProcess (), query_hdl_close_req_evt
,
637 GetCurrentProcess (),
638 &ftp
->query_hdl_close_req_evt
,
639 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
645 ReleaseMutex (hdl_cnt_mtx
);
647 debug_printf ("res %d", res
);
652 fhandler_pipe::close ()
656 release_select_sem ("close");
657 CloseHandle (select_sem
);
660 CloseHandle (read_mtx
);
661 WaitForSingleObject (hdl_cnt_mtx
, INFINITE
);
663 CloseHandle (query_hdl
);
664 if (query_hdl_close_req_evt
)
665 CloseHandle (query_hdl_close_req_evt
);
666 int ret
= fhandler_base::close ();
667 ReleaseMutex (hdl_cnt_mtx
);
668 CloseHandle (hdl_cnt_mtx
);
670 CloseHandle (query_hdl_proc
);
674 #define PIPE_INTRO "\\\\.\\pipe\\cygwin-"
676 /* Create a pipe, and return handles to the read and write ends,
677 just like CreatePipe, but ensure that the write end permits
678 FILE_READ_ATTRIBUTES access, on later versions of win32 where
679 this is supported. This access is needed by NtQueryInformationFile,
680 which is used to implement select and nonblocking writes.
681 Note that the return value is either 0 or GetLastError,
682 unlike CreatePipe, which returns a bool for success or failure. */
684 fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr
, PHANDLE r
, PHANDLE w
,
685 DWORD psize
, const char *name
, DWORD open_mode
,
688 /* Default to error. */
694 /* Ensure that there is enough pipe buffer space for atomic writes. */
696 psize
= DEFAULT_PIPEBUFSIZE
;
698 char pipename
[MAX_PATH
];
699 size_t len
= __small_sprintf (pipename
, PIPE_INTRO
"%S-",
700 &cygheap
->installation_key
);
701 DWORD pipe_mode
= PIPE_READMODE_BYTE
| PIPE_REJECT_REMOTE_CLIENTS
;
703 pipe_mode
|= pipe_byte
? PIPE_TYPE_BYTE
: PIPE_TYPE_MESSAGE
;
705 pipe_mode
|= PIPE_TYPE_MESSAGE
;
707 if (!name
|| (open_mode
& PIPE_ADD_PID
))
709 len
+= __small_sprintf (pipename
+ len
, "%u-", GetCurrentProcessId ());
710 open_mode
&= ~PIPE_ADD_PID
;
714 len
+= __small_sprintf (pipename
+ len
, "%s", name
);
716 open_mode
|= PIPE_ACCESS_INBOUND
| FILE_FLAG_FIRST_PIPE_INSTANCE
;
718 /* Retry CreateNamedPipe as long as the pipe name is in use.
719 Retrying will probably never be necessary, but we want
720 to be as robust as possible. */
724 static volatile ULONG pipe_unique_id
;
727 LONG id
= InterlockedIncrement ((LONG
*) &pipe_unique_id
);
728 __small_sprintf (pipename
+ len
, "pipe-%p", id
);
730 *unique_id
= ((int64_t) id
<< 32 | GetCurrentProcessId ());
733 debug_printf ("name %s, size %u, mode %s", pipename
, psize
,
734 (pipe_mode
& PIPE_TYPE_MESSAGE
)
735 ? "PIPE_TYPE_MESSAGE" : "PIPE_TYPE_BYTE");
737 /* Use CreateNamedPipe instead of CreatePipe, because the latter
738 returns a write handle that does not permit FILE_READ_ATTRIBUTES
739 access, on versions of win32 earlier than WinXP SP2.
740 CreatePipe also stupidly creates a full duplex pipe, which is
741 a waste, since only a single direction is actually used.
742 It's important to only allow a single instance, to ensure that
743 the pipe was not created earlier by some other process, even if
744 the pid has been reused.
746 Note that the write side of the pipe is opened as PIPE_TYPE_MESSAGE.
747 This *seems* to more closely mimic Linux pipe behavior and is
748 definitely required for pty handling since fhandler_pty_master
749 writes to the pipe in chunks, terminated by newline when CANON mode
751 *r
= CreateNamedPipe (pipename
, open_mode
, pipe_mode
, 1, psize
,
752 psize
, NMPWAIT_USE_DEFAULT_WAIT
, sa_ptr
);
754 if (*r
!= INVALID_HANDLE_VALUE
)
756 debug_printf ("pipe read handle %p", *r
);
761 err
= GetLastError ();
764 case ERROR_PIPE_BUSY
:
765 /* The pipe is already open with compatible parameters.
766 Pick a new name and retry. */
767 debug_printf ("pipe busy", !name
? ", retrying" : "");
771 case ERROR_ACCESS_DENIED
:
772 /* The pipe is already open with incompatible parameters.
773 Pick a new name and retry. */
774 debug_printf ("pipe access denied%s", !name
? ", retrying" : "");
780 err
= GetLastError ();
781 debug_printf ("failed, %E");
793 debug_printf ("pipe write handle NULL");
796 debug_printf ("CreateFile: name %s", pipename
);
798 /* Open the named pipe for writing.
799 Be sure to permit FILE_READ_ATTRIBUTES access. */
800 DWORD access
= GENERIC_WRITE
| FILE_READ_ATTRIBUTES
;
801 if ((open_mode
& PIPE_ACCESS_DUPLEX
) == PIPE_ACCESS_DUPLEX
)
802 access
|= GENERIC_READ
| FILE_WRITE_ATTRIBUTES
;
803 *w
= CreateFile (pipename
, access
, 0, sa_ptr
, OPEN_EXISTING
,
804 open_mode
& FILE_FLAG_OVERLAPPED
, 0);
806 if (!*w
|| *w
== INVALID_HANDLE_VALUE
)
809 DWORD err
= GetLastError ();
810 debug_printf ("CreateFile failed, r %p, %E", r
);
817 debug_printf ("pipe write handle %p", *w
);
825 is_running_as_service (void)
827 return check_token_membership (well_known_service_sid
)
828 || cygheap
->user
.saved_sid () == well_known_system_sid
;
831 /* The next version of fhandler_pipe::create used to call the previous
832 version. But the read handle created by the latter doesn't have
833 FILE_WRITE_ATTRIBUTES access unless the pipe is created with
834 PIPE_ACCESS_DUPLEX, and it doesn't seem possible to add that access
835 right. This causes set_pipe_non_blocking to fail.
837 To fix this we will define a helper function 'nt_create' that is
838 similar to the above fhandler_pipe::create but uses
839 NtCreateNamedPipeFile instead of CreateNamedPipe; this gives more
840 flexibility in setting the access rights. We will use this helper
841 function in the version of fhandler_pipe::create below, which
842 suffices for all of our uses of set_pipe_non_blocking. For
843 simplicity, nt_create will omit the 'open_mode' and 'name'
844 parameters, which aren't needed for our purposes. */
846 static int nt_create (LPSECURITY_ATTRIBUTES
, HANDLE
&, HANDLE
&, DWORD
,
850 fhandler_pipe::create (fhandler_pipe
*fhs
[2], unsigned psize
, int mode
)
853 SECURITY_ATTRIBUTES
*sa
= sec_none_cloexec (mode
);
857 int ret
= nt_create (sa
, r
, w
, psize
, &unique_id
);
860 __seterrno_from_win_error (ret
);
863 if ((fhs
[0] = (fhandler_pipe
*) build_fh_dev (*piper_dev
)) == NULL
)
864 goto err_close_rw_handle
;
865 if ((fhs
[1] = (fhandler_pipe
*) build_fh_dev (*pipew_dev
)) == NULL
)
866 goto err_delete_fhs0
;
867 mode
|= mode
& O_TEXT
?: O_BINARY
;
868 fhs
[0]->init (r
, FILE_CREATE_PIPE_INSTANCE
| GENERIC_READ
, mode
, unique_id
);
869 fhs
[1]->init (w
, FILE_CREATE_PIPE_INSTANCE
| GENERIC_WRITE
, mode
, unique_id
);
871 /* For the read side of the pipe, add a mutex. See raw_read for the
873 fhs
[0]->read_mtx
= CreateMutexW (sa
, FALSE
, NULL
);
874 if (!fhs
[0]->read_mtx
)
875 goto err_delete_fhs1
;
877 fhs
[0]->select_sem
= CreateSemaphore (sa
, 0, INT32_MAX
, NULL
);
878 if (!fhs
[0]->select_sem
)
879 goto err_close_read_mtx
;
880 if (!DuplicateHandle (GetCurrentProcess (), fhs
[0]->select_sem
,
881 GetCurrentProcess (), &fhs
[1]->select_sem
,
882 0, sa
->bInheritHandle
, DUPLICATE_SAME_ACCESS
))
883 goto err_close_select_sem0
;
885 if (is_running_as_service () &&
886 !DuplicateHandle (GetCurrentProcess (), r
,
887 GetCurrentProcess (), &fhs
[1]->query_hdl
,
888 FILE_READ_DATA
, sa
->bInheritHandle
, 0))
889 goto err_close_select_sem1
;
891 fhs
[0]->hdl_cnt_mtx
= CreateMutexW (sa
, FALSE
, NULL
);
892 if (!fhs
[0]->hdl_cnt_mtx
)
893 goto err_close_query_hdl
;
894 if (!DuplicateHandle (GetCurrentProcess (), fhs
[0]->hdl_cnt_mtx
,
895 GetCurrentProcess (), &fhs
[1]->hdl_cnt_mtx
,
896 0, sa
->bInheritHandle
, DUPLICATE_SAME_ACCESS
))
897 goto err_close_hdl_cnt_mtx0
;
899 if (fhs
[1]->query_hdl
)
901 fhs
[1]->query_hdl_close_req_evt
= CreateEvent (sa
, TRUE
, FALSE
, NULL
);
902 if (!fhs
[1]->query_hdl_close_req_evt
)
903 goto err_close_hdl_cnt_mtx1
;
909 err_close_hdl_cnt_mtx1
:
910 CloseHandle (fhs
[1]->hdl_cnt_mtx
);
911 err_close_hdl_cnt_mtx0
:
912 CloseHandle (fhs
[0]->hdl_cnt_mtx
);
914 if (fhs
[1]->query_hdl
)
915 CloseHandle (fhs
[1]->query_hdl
);
916 err_close_select_sem1
:
917 CloseHandle (fhs
[1]->select_sem
);
918 err_close_select_sem0
:
919 CloseHandle (fhs
[0]->select_sem
);
921 CloseHandle (fhs
[0]->read_mtx
);
930 debug_printf ("%R = pipe([%p, %p], %d, %y)",
931 res
, fhs
[0], fhs
[1], psize
, mode
);
936 nt_create (LPSECURITY_ATTRIBUTES sa_ptr
, HANDLE
&r
, HANDLE
&w
,
937 DWORD psize
, int64_t *unique_id
)
942 OBJECT_ATTRIBUTES attr
;
944 LARGE_INTEGER timeout
;
946 /* Default to error. */
950 status
= fhandler_base::npfs_handle (npfsh
);
951 if (!NT_SUCCESS (status
))
953 __seterrno_from_nt_status (status
);
954 return GetLastError ();
957 /* Ensure that there is enough pipe buffer space for atomic writes. */
959 psize
= DEFAULT_PIPEBUFSIZE
;
961 UNICODE_STRING pipename
;
962 WCHAR pipename_buf
[MAX_PATH
];
963 size_t len
= __small_swprintf (pipename_buf
, L
"%S-%u-",
964 &cygheap
->installation_key
,
965 GetCurrentProcessId ());
967 access
= GENERIC_READ
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
;
968 access
|= FILE_WRITE_EA
; /* Add this right as a marker of cygwin read pipe */
970 ULONG pipe_type
= pipe_byte
? FILE_PIPE_BYTE_STREAM_TYPE
971 : FILE_PIPE_MESSAGE_TYPE
;
973 /* Retry NtCreateNamedPipeFile as long as the pipe name is in use.
974 Retrying will probably never be necessary, but we want
975 to be as robust as possible. */
979 static volatile ULONG pipe_unique_id
;
980 LONG id
= InterlockedIncrement ((LONG
*) &pipe_unique_id
);
981 __small_swprintf (pipename_buf
+ len
, L
"pipe-nt-%p", id
);
983 *unique_id
= ((int64_t) id
<< 32 | GetCurrentProcessId ());
985 debug_printf ("name %W, size %u, mode %s", pipename_buf
, psize
,
986 (pipe_type
& FILE_PIPE_MESSAGE_TYPE
)
987 ? "PIPE_TYPE_MESSAGE" : "PIPE_TYPE_BYTE");
989 RtlInitUnicodeString (&pipename
, pipename_buf
);
991 InitializeObjectAttributes (&attr
, &pipename
,
992 sa_ptr
->bInheritHandle
? OBJ_INHERIT
: 0,
993 npfsh
, sa_ptr
->lpSecurityDescriptor
);
995 timeout
.QuadPart
= -500000;
996 /* Set FILE_SYNCHRONOUS_IO_NONALERT flag so that native
997 C# programs work with cygwin pipe. */
998 status
= NtCreateNamedPipeFile (&r
, access
, &attr
, &io
,
999 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1001 FILE_SYNCHRONOUS_IO_NONALERT
, pipe_type
,
1002 FILE_PIPE_BYTE_STREAM_MODE
,
1003 0, 1, psize
, psize
, &timeout
);
1005 if (NT_SUCCESS (status
))
1007 debug_printf ("pipe read handle %p", r
);
1014 case STATUS_PIPE_BUSY
:
1015 case STATUS_INSTANCE_NOT_AVAILABLE
:
1016 case STATUS_PIPE_NOT_AVAILABLE
:
1017 /* The pipe is already open with compatible parameters.
1018 Pick a new name and retry. */
1019 debug_printf ("pipe busy, retrying");
1022 case STATUS_ACCESS_DENIED
:
1023 /* The pipe is already open with incompatible parameters.
1024 Pick a new name and retry. */
1025 debug_printf ("pipe access denied, retrying");
1030 __seterrno_from_nt_status (status
);
1031 err
= GetLastError ();
1032 debug_printf ("failed, %E");
1044 debug_printf ("NtOpenFile: name %S", &pipename
);
1046 access
= GENERIC_WRITE
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
;
1047 status
= NtOpenFile (&w
, access
, &attr
, &io
, 0, 0);
1048 if (!NT_SUCCESS (status
))
1050 DWORD err
= GetLastError ();
1051 debug_printf ("NtOpenFile failed, r %p, %E", r
);
1062 /* Called by dtable::init_std_file_from_handle for stdio handles
1063 inherited from non-Cygwin processes. */
1065 fhandler_pipe::set_pipe_buf_size ()
1069 FILE_PIPE_LOCAL_INFORMATION fpli
;
1071 status
= NtQueryInformationFile (get_handle (), &io
, &fpli
, sizeof fpli
,
1072 FilePipeLocalInformation
);
1073 if (NT_SUCCESS (status
))
1074 pipe_buf_size
= fpli
.InboundQuota
;
1078 fhandler_pipe::ioctl (unsigned int cmd
, void *p
)
1085 if (get_device () == FH_PIPEW
)
1090 if (!PeekNamedPipe (get_handle (), NULL
, 0, NULL
, (DWORD
*) &n
, NULL
))
1097 return fhandler_base::ioctl (cmd
, p
);
1105 fhandler_pipe::fcntl (int cmd
, intptr_t arg
)
1108 return fhandler_base::fcntl (cmd
, arg
);
1110 const bool was_nonblocking
= is_nonblocking ();
1111 int res
= fhandler_base::fcntl (cmd
, arg
);
1112 const bool now_nonblocking
= is_nonblocking ();
1113 /* Do not set blocking mode for read pipe to allow signal handling
1114 even with FILE_SYNCHRONOUS_IO_NONALERT. */
1115 if (now_nonblocking
!= was_nonblocking
&& get_device () != FH_PIPER
)
1116 set_pipe_non_blocking (now_nonblocking
);
1121 fhandler_pipe::fstat (struct stat
*buf
)
1123 int ret
= fhandler_base::fstat (buf
);
1126 buf
->st_dev
= FH_PIPE
;
1127 if (!(buf
->st_ino
= get_plain_ino ()))
1128 sscanf (get_name (), "/proc/%*d/fd/pipe:[%llu]",
1129 (long long *) &buf
->st_ino
);
1135 fhandler_pipe::fstatvfs (struct statvfs
*sfs
)
1142 fhandler_pipe::temporary_query_hdl ()
1144 if (get_dev () != FH_PIPEW
)
1150 OBJECT_NAME_INFORMATION
*ntfn
= (OBJECT_NAME_INFORMATION
*) tp
.w_get ();
1152 /* Try process handle opened and pipe handle value cached first
1153 in order to reduce overhead. */
1154 if (query_hdl_proc
&& query_hdl_value
)
1157 if (!DuplicateHandle (query_hdl_proc
, query_hdl_value
,
1158 GetCurrentProcess (), &h
, FILE_READ_DATA
, 0, 0))
1161 status
= NtQueryObject (h
, ObjectNameInformation
, ntfn
, 65536, &len
);
1162 if (!NT_SUCCESS (status
) || !ntfn
->Name
.Buffer
)
1164 ntfn
->Name
.Buffer
[ntfn
->Name
.Length
/ sizeof (WCHAR
)] = L
'\0';
1168 if (swscanf (ntfn
->Name
.Buffer
,
1169 L
"\\Device\\NamedPipe\\%llx-%u-pipe-nt-0x%x",
1170 &key
, &pid
, &id
) == 3 &&
1171 key
== pipename_key
&& pid
== pipename_pid
&& id
== pipename_id
)
1176 CloseHandle (query_hdl_proc
);
1177 query_hdl_proc
= NULL
;
1178 query_hdl_value
= NULL
;
1181 status
= NtQueryObject (get_handle (), ObjectNameInformation
, ntfn
,
1183 if (!NT_SUCCESS (status
) || !ntfn
->Name
.Buffer
)
1184 return NULL
; /* Non cygwin pipe? */
1185 WCHAR name
[MAX_PATH
];
1186 int namelen
= min (ntfn
->Name
.Length
/ sizeof (WCHAR
), MAX_PATH
-1);
1187 memcpy (name
, ntfn
->Name
.Buffer
, namelen
* sizeof (WCHAR
));
1188 name
[namelen
] = L
'\0';
1189 if (swscanf (name
, L
"\\Device\\NamedPipe\\%llx-%u-pipe-nt-0x%x",
1190 &pipename_key
, &pipename_pid
, &pipename_id
) != 3)
1191 return NULL
; /* Non cygwin pipe? */
1193 return get_query_hdl_per_process (name
, ntfn
); /* Since Win8 */
1197 fhandler_pipe::get_query_hdl_per_process (WCHAR
*name
,
1198 OBJECT_NAME_INFORMATION
*ntfn
)
1202 DWORD n_process
= 256;
1203 PSYSTEM_PROCESS_INFORMATION spi
;
1205 { /* Enumerate processes */
1206 DWORD nbytes
= n_process
* sizeof (SYSTEM_PROCESS_INFORMATION
);
1207 spi
= (PSYSTEM_PROCESS_INFORMATION
) HeapAlloc (GetProcessHeap (),
1211 status
= NtQuerySystemInformation (SystemProcessInformation
,
1213 if (NT_SUCCESS (status
))
1215 HeapFree (GetProcessHeap (), 0, spi
);
1218 while (n_process
< (1L<<20) && status
== STATUS_INFO_LENGTH_MISMATCH
);
1219 if (!NT_SUCCESS (status
))
1222 /* In most cases, it is faster to check the processes in reverse order.
1223 To do this, store PIDs into an array. */
1224 DWORD
*proc_pids
= (DWORD
*) HeapAlloc (GetProcessHeap (), 0,
1225 n_process
* sizeof (DWORD
));
1228 HeapFree (GetProcessHeap (), 0, spi
);
1231 PSYSTEM_PROCESS_INFORMATION p
= spi
;
1235 proc_pids
[n_process
++] = (DWORD
)(intptr_t) p
->UniqueProcessId
;
1236 if (!p
->NextEntryOffset
)
1238 p
= (PSYSTEM_PROCESS_INFORMATION
) ((char *) p
+ p
->NextEntryOffset
);
1240 HeapFree (GetProcessHeap (), 0, spi
);
1242 for (LONG i
= (LONG
) n_process
- 1; i
>= 0; i
--)
1244 HANDLE proc
= OpenProcess (PROCESS_DUP_HANDLE
1245 | PROCESS_QUERY_INFORMATION
,
1250 /* Retrieve process handles */
1251 DWORD n_handle
= 256;
1252 PPROCESS_HANDLE_SNAPSHOT_INFORMATION phi
;
1255 DWORD nbytes
= 2 * sizeof (ULONG_PTR
) +
1256 n_handle
* sizeof (PROCESS_HANDLE_TABLE_ENTRY_INFO
);
1257 phi
= (PPROCESS_HANDLE_SNAPSHOT_INFORMATION
)
1258 HeapAlloc (GetProcessHeap (), 0, nbytes
);
1261 /* NtQueryInformationProcess can return STATUS_SUCCESS with
1262 invalid handle data for certain processes. See
1263 https://github.com/processhacker/processhacker/blob/05f5e9fa477dcaa1709d9518170d18e1b3b8330d/phlib/native.c#L5754.
1264 We need to ensure that NumberOfHandles is zero in this
1265 case to avoid a crash in the for loop below. */
1266 phi
->NumberOfHandles
= 0;
1267 status
= NtQueryInformationProcess (proc
, ProcessHandleInformation
,
1269 if (NT_SUCCESS (status
))
1271 HeapFree (GetProcessHeap (), 0, phi
);
1274 while (n_handle
< (1L<<20) && status
== STATUS_INFO_LENGTH_MISMATCH
);
1275 if (!NT_SUCCESS (status
))
1278 /* Sanity check in case Microsoft changes
1279 NtQueryInformationProcess and the initialization of
1280 NumberOfHandles above is no longer sufficient. */
1281 assert (phi
->NumberOfHandles
<= n_handle
);
1282 for (ULONG j
= 0; j
< phi
->NumberOfHandles
; j
++)
1284 /* Check for the peculiarity of cygwin read pipe */
1285 const ULONG access
= FILE_READ_DATA
| FILE_READ_EA
1286 | FILE_WRITE_EA
/* marker */
1287 | FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
1288 | READ_CONTROL
| SYNCHRONIZE
;
1289 if (phi
->Handles
[j
].GrantedAccess
!= access
)
1292 /* Retrieve handle */
1293 HANDLE h
= (HANDLE
)(intptr_t) phi
->Handles
[j
].HandleValue
;
1294 BOOL res
= DuplicateHandle (proc
, h
, GetCurrentProcess (), &h
,
1295 FILE_READ_DATA
, 0, 0);
1299 /* Check object name */
1300 status
= NtQueryObject (h
, ObjectNameInformation
,
1302 if (!NT_SUCCESS (status
) || !ntfn
->Name
.Buffer
)
1304 ntfn
->Name
.Buffer
[ntfn
->Name
.Length
/ sizeof (WCHAR
)] = L
'\0';
1305 if (wcscmp (name
, ntfn
->Name
.Buffer
) == 0)
1307 query_hdl_proc
= proc
;
1308 query_hdl_value
= (HANDLE
)(intptr_t) phi
->Handles
[j
].HandleValue
;
1309 HeapFree (GetProcessHeap (), 0, phi
);
1310 HeapFree (GetProcessHeap (), 0, proc_pids
);
1316 HeapFree (GetProcessHeap (), 0, phi
);
1320 HeapFree (GetProcessHeap (), 0, proc_pids
);