1 /* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes.
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
10 #include <w32api/winioctl.h>
11 #include "miscfuncs.h"
21 #include "shared_info.h"
24 #include <sys/param.h>
29 FIFOs are implemented via Windows named pipes. The server end of
30 the pipe corresponds to an fhandler_fifo open for reading (a.k.a,
31 a "reader"), and the client end corresponds to an fhandler_fifo
32 open for writing (a.k.a, a "writer").
34 The server can have multiple instances. The reader (assuming for
35 the moment that there is only one) creates a pipe instance for
36 each writer that opens. The reader maintains a list of
37 "fifo_client_handler" structures, one for each writer. A
38 fifo_client_handler contains the handle for the pipe server
39 instance and information about the state of the connection with
40 the writer. Access to the list is controlled by a
43 The reader runs a "fifo_reader_thread" that creates new pipe
44 instances as needed and listens for client connections.
46 The connection state of a fifo_client_handler has one of the
47 following values, in which order is important:
57 It can be changed in the following places:
59 - It is set to fc_listening when the pipe instance is created.
61 - It is set to fc_connected when the fifo_reader_thread detects
64 - It is set to a value reported by the O/S when
65 query_and_set_state is called. This can happen in
66 select.cc:peek_fifo and a couple other places.
68 - It is set to fc_disconnected by raw_read when an attempt to
69 read yields STATUS_PIPE_BROKEN.
71 - It is set to fc_error in various places when unexpected
74 State changes are always guarded by fifo_client_lock.
76 If there are multiple readers open, only one of them, called the
77 "owner", maintains the fifo_client_handler list. The owner is
78 therefore the only reader that can read at any given time. If a
79 different reader wants to read, it has to take ownership and
80 duplicate the fifo_client_handler list.
82 A reader that is not an owner also runs a fifo_reader_thread,
83 which is mostly idle. The thread wakes up if that reader might
84 need to take ownership.
86 There is a block of named shared memory, accessible to all
87 fhandlers for a given FIFO. It keeps track of the number of open
88 readers and writers; it contains information needed for the owner
89 change process; and it contains some locks to prevent races and
90 deadlocks between the various threads.
92 The shared memory is created by the first reader to open the
93 FIFO. It is opened by subsequent readers and by all writers. It
94 is destroyed by Windows when the last handle to it is closed.
96 If a handle to it somehow remains open after all processes
97 holding file descriptors to the FIFO have closed, the shared
98 memory can persist and be reused with stale data by the next
99 process that opens the FIFO. So far I've seen this happen only
100 as a result of a bug in the code, but there are some debug_printf
101 statements in fhandler_fifo::open to help detect this if it
104 At this writing, I know of only one application (Midnight
105 Commander when running under tcsh) that *explicitly* opens two
106 readers of a FIFO. But many applications will have multiple
107 readers open via dup/fork/exec.
111 /* This is only to be used for writers. When reading,
112 STATUS_PIPE_EMPTY simply means there's no data to be read. */
113 #define STATUS_PIPE_IS_CLOSED(status) \
114 ({ NTSTATUS _s = (status); \
115 _s == STATUS_PIPE_CLOSING \
116 || _s == STATUS_PIPE_BROKEN \
117 || _s == STATUS_PIPE_EMPTY; })
119 #define STATUS_PIPE_NO_INSTANCE_AVAILABLE(status) \
120 ({ NTSTATUS _s = (status); \
121 _s == STATUS_INSTANCE_NOT_AVAILABLE \
122 || _s == STATUS_PIPE_NOT_AVAILABLE \
123 || _s == STATUS_PIPE_BUSY; })
125 /* Number of pages reserved for shared_fc_handler. */
126 #define SH_FC_HANDLER_PAGES 100
128 static NO_COPY fifo_reader_id_t null_fr_id
= { .winpid
= 0, .fh
= NULL
};
130 fhandler_fifo::fhandler_fifo ():
131 fhandler_pipe_fifo (),
132 read_ready (NULL
), write_ready (NULL
), writer_opening (NULL
),
133 owner_needed_evt (NULL
), owner_found_evt (NULL
), update_needed_evt (NULL
),
134 cancel_evt (NULL
), thr_sync_evt (NULL
), pipe_name_buf (NULL
),
135 fc_handler (NULL
), shandlers (0), nhandlers (0),
136 reader (false), writer (false), duplexer (false),
137 me (null_fr_id
), shmem_handle (NULL
), shmem (NULL
),
138 shared_fc_hdl (NULL
), shared_fc_handler (NULL
)
140 need_fork_fixup (true);
144 fhandler_fifo::get_pipe_name ()
148 pipe_name
.Length
= CYGWIN_FIFO_PIPE_NAME_LEN
* sizeof (WCHAR
);
149 pipe_name
.MaximumLength
= pipe_name
.Length
+ sizeof (WCHAR
);
150 pipe_name_buf
= (PWCHAR
) cmalloc_abort (HEAP_STR
,
151 pipe_name
.MaximumLength
);
152 pipe_name
.Buffer
= pipe_name_buf
;
153 __small_swprintf (pipe_name_buf
, L
"%S-fifo.%08x.%016X",
154 &cygheap
->installation_key
, get_dev (), get_ino ());
159 inline PSECURITY_ATTRIBUTES
160 sec_user_cloexec (bool cloexec
, PSECURITY_ATTRIBUTES sa
, PSID sid
)
162 return cloexec
? sec_user_nih (sa
, sid
) : sec_user (sa
, sid
);
169 OBJECT_ATTRIBUTES attr
;
172 InitializeObjectAttributes (&attr
, NULL
, 0, NULL
, NULL
);
173 status
= NtCreateEvent (&evt
, EVENT_ALL_ACCESS
, &attr
,
174 NotificationEvent
, FALSE
);
175 if (!NT_SUCCESS (status
))
176 __seterrno_from_nt_status (status
);
182 set_pipe_non_blocking (HANDLE ph
, bool nonblocking
)
186 FILE_PIPE_INFORMATION fpi
;
188 fpi
.ReadMode
= FILE_PIPE_MESSAGE_MODE
;
189 fpi
.CompletionMode
= nonblocking
? FILE_PIPE_COMPLETE_OPERATION
190 : FILE_PIPE_QUEUE_OPERATION
;
191 status
= NtSetInformationFile (ph
, &io
, &fpi
, sizeof fpi
,
192 FilePipeInformation
);
193 if (!NT_SUCCESS (status
))
194 debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status
);
197 /* Called when a FIFO is first opened for reading and again each time
198 a new client handler is needed. Each pipe instance is created in
199 blocking mode so that we can easily wait for a connection. After
200 it is connected, it is put in nonblocking mode. */
202 fhandler_fifo::create_pipe_instance ()
208 OBJECT_ATTRIBUTES attr
;
212 ULONG nonblocking
= FILE_PIPE_QUEUE_OPERATION
;
213 ULONG max_instances
= -1;
214 LARGE_INTEGER timeout
;
216 status
= npfs_handle (npfsh
);
217 if (!NT_SUCCESS (status
))
219 __seterrno_from_nt_status (status
);
222 access
= GENERIC_READ
| FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
224 sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
225 hattr
= (openflags
& O_CLOEXEC
? 0 : OBJ_INHERIT
) | OBJ_CASE_INSENSITIVE
;
226 InitializeObjectAttributes (&attr
, get_pipe_name (),
228 timeout
.QuadPart
= -500000;
229 status
= NtCreateNamedPipeFile (&ph
, access
, &attr
, &io
, sharing
,
231 FILE_PIPE_MESSAGE_TYPE
232 | FILE_PIPE_REJECT_REMOTE_CLIENTS
,
233 FILE_PIPE_MESSAGE_MODE
,
234 nonblocking
, max_instances
,
235 DEFAULT_PIPEBUFSIZE
, DEFAULT_PIPEBUFSIZE
,
237 if (!NT_SUCCESS (status
))
238 __seterrno_from_nt_status (status
);
242 /* Connect to a pipe instance. */
244 fhandler_fifo::open_pipe (HANDLE
& ph
)
249 OBJECT_ATTRIBUTES attr
;
253 status
= npfs_handle (npfsh
);
254 if (!NT_SUCCESS (status
))
256 access
= GENERIC_WRITE
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
;
257 InitializeObjectAttributes (&attr
, get_pipe_name (),
258 openflags
& O_CLOEXEC
? 0 : OBJ_INHERIT
,
260 sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
261 return NtOpenFile (&ph
, access
, &attr
, &io
, sharing
, 0);
264 /* Wait up to 100ms for a pipe instance to be available, then connect. */
266 fhandler_fifo::wait_open_pipe (HANDLE
& ph
)
273 PFILE_PIPE_WAIT_FOR_BUFFER pwbuf
;
275 LONGLONG orig_timeout
= -100 * NS100PERSEC
/ MSPERSEC
; /* 100ms */
277 status
= npfs_handle (npfsh
);
278 if (!NT_SUCCESS (status
))
280 if (!(evt
= create_event ()))
281 api_fatal ("Can't create event, %E");
283 = offsetof (FILE_PIPE_WAIT_FOR_BUFFER
, Name
) + get_pipe_name ()->Length
;
284 pwbuf
= (PFILE_PIPE_WAIT_FOR_BUFFER
) alloca (pwbuf_size
);
285 pwbuf
->Timeout
.QuadPart
= orig_timeout
;
286 pwbuf
->NameLength
= get_pipe_name ()->Length
;
287 pwbuf
->TimeoutSpecified
= TRUE
;
288 memcpy (pwbuf
->Name
, get_pipe_name ()->Buffer
, get_pipe_name ()->Length
);
289 stamp
= get_clock (CLOCK_MONOTONIC
)->n100secs ();
294 status
= NtFsControlFile (npfsh
, evt
, NULL
, NULL
, &io
, FSCTL_PIPE_WAIT
,
295 pwbuf
, pwbuf_size
, NULL
, 0);
296 if (status
== STATUS_PENDING
)
298 if (WaitForSingleObject (evt
, INFINITE
) == WAIT_OBJECT_0
)
301 api_fatal ("WFSO failed, %E");
303 if (NT_SUCCESS (status
))
304 status
= open_pipe (ph
);
305 if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status
))
307 /* Another writer has grabbed the pipe instance. Adjust
308 the timeout and keep waiting if there's time left. */
309 pwbuf
->Timeout
.QuadPart
= orig_timeout
310 + get_clock (CLOCK_MONOTONIC
)->n100secs () - stamp
;
311 if (pwbuf
->Timeout
.QuadPart
< 0)
314 status
= STATUS_IO_TIMEOUT
;
322 /* Always called with fifo_client_lock in place. */
324 fhandler_fifo::add_client_handler (bool new_pipe_instance
)
326 fifo_client_handler fc
;
328 if (nhandlers
>= shandlers
)
330 void *temp
= realloc (fc_handler
,
331 (shandlers
+= 64) * sizeof (fc_handler
[0]));
338 fc_handler
= (fifo_client_handler
*) temp
;
340 if (new_pipe_instance
)
342 HANDLE ph
= create_pipe_instance ();
346 fc
.set_state (fc_listening
);
348 fc_handler
[nhandlers
++] = fc
;
352 /* Always called with fifo_client_lock in place. Delete a
353 client_handler by swapping it with the last one in the list. */
355 fhandler_fifo::delete_client_handler (int i
)
357 fc_handler
[i
].close ();
359 fc_handler
[i
] = fc_handler
[nhandlers
];
362 /* Delete handlers that we will never read from. Always called with
363 fifo_client_lock in place. */
365 fhandler_fifo::cleanup_handlers ()
367 /* Work from the top down to try to avoid copying. */
368 for (int i
= nhandlers
- 1; i
>= 0; --i
)
369 if (fc_handler
[i
].get_state () < fc_connected
)
370 delete_client_handler (i
);
373 /* Always called with fifo_client_lock in place. */
375 fhandler_fifo::record_connection (fifo_client_handler
& fc
, bool set
,
376 fifo_client_connect_state s
)
380 set_pipe_non_blocking (fc
.h
, true);
383 /* Called from fifo_reader_thread_func with owner_lock in place. */
385 fhandler_fifo::update_my_handlers ()
389 close_all_handlers ();
390 fifo_reader_id_t prev
= get_prev_owner ();
393 debug_printf ("No previous owner to copy handles from");
397 if (prev
.winpid
== me
.winpid
)
398 prev_proc
= GetCurrentProcess ();
400 prev_proc
= OpenProcess (PROCESS_DUP_HANDLE
, false, prev
.winpid
);
402 api_fatal ("Can't open process of previous owner, %E");
405 for (int i
= 0; i
< get_shared_nhandlers (); i
++)
407 if (add_client_handler (false) < 0)
408 api_fatal ("Can't add client handler, %E");
409 fifo_client_handler
&fc
= fc_handler
[nhandlers
- 1];
410 if (!DuplicateHandle (prev_proc
, shared_fc_handler
[i
].h
,
411 GetCurrentProcess (), &fc
.h
, 0,
412 !close_on_exec (), DUPLICATE_SAME_ACCESS
))
414 debug_printf ("Can't duplicate handle of previous owner, %E");
416 fc
.set_state (fc_error
);
417 fc
.last_read
= false;
422 fc
.set_state (shared_fc_handler
[i
].get_state ());
423 fc
.last_read
= shared_fc_handler
[i
].last_read
;
426 fifo_client_unlock ();
428 set_prev_owner (null_fr_id
);
432 /* Always called with fifo_client_lock and owner_lock in place. */
434 fhandler_fifo::update_shared_handlers ()
437 if (nhandlers
> get_shared_shandlers ())
439 if (remap_shared_fc_handler (nhandlers
* sizeof (fc_handler
[0])) < 0)
442 set_shared_nhandlers (nhandlers
);
443 memcpy (shared_fc_handler
, fc_handler
, nhandlers
* sizeof (fc_handler
[0]));
444 shared_fc_handler_updated (true);
450 fifo_reader_thread (LPVOID param
)
452 fhandler_fifo
*fh
= (fhandler_fifo
*) param
;
453 return fh
->fifo_reader_thread_func ();
457 fhandler_fifo::fifo_reader_thread_func ()
461 if (!(conn_evt
= CreateEvent (NULL
, false, false, NULL
)))
462 api_fatal ("Can't create connection event, %E");
466 fifo_reader_id_t cur_owner
, pending_owner
;
467 bool idle
= false, take_ownership
= false;
470 cur_owner
= get_owner ();
471 pending_owner
= get_pending_owner ();
475 if (pending_owner
== me
)
476 take_ownership
= true;
477 else if (cur_owner
!= me
)
481 /* I'm the owner but someone else wants to be. Have I
482 already seen and reacted to update_needed_evt? */
483 if (WaitForSingleObject (update_needed_evt
, 0) == WAIT_OBJECT_0
)
487 if (update_shared_handlers () < 0)
488 api_fatal ("Can't update shared handlers, %E");
489 fifo_client_unlock ();
492 /* Yield to pending owner. */
498 take_ownership
= true;
499 else if (cur_owner
!= me
)
502 /* I'm the owner and there's no pending owner. */
507 HANDLE w
[2] = { owner_needed_evt
, cancel_evt
};
508 switch (WaitForMultipleObjects (2, w
, false, INFINITE
))
512 case WAIT_OBJECT_0
+ 1:
515 api_fatal ("WFMO failed, %E");
518 else if (take_ownership
)
520 if (!shared_fc_handler_updated ())
523 if (IsEventSignalled (cancel_evt
))
530 set_pending_owner (null_fr_id
);
531 if (update_my_handlers () < 0)
532 debug_printf ("error updating my handlers, %E");
534 /* Fall through to owner_listen. */
541 if (add_client_handler () < 0)
542 api_fatal ("Can't add a client handler, %E");
544 /* Listen for a writer to connect to the new client handler. */
545 fifo_client_handler
& fc
= fc_handler
[nhandlers
- 1];
546 fifo_client_unlock ();
547 shared_fc_handler_updated (false);
554 status
= NtFsControlFile (fc
.h
, conn_evt
, NULL
, NULL
, &io
,
555 FSCTL_PIPE_LISTEN
, NULL
, 0, NULL
, 0);
556 if (status
== STATUS_PENDING
)
558 HANDLE w
[3] = { conn_evt
, update_needed_evt
, cancel_evt
};
559 switch (WaitForMultipleObjects (3, w
, false, INFINITE
))
563 debug_printf ("NtFsControlFile STATUS_PENDING, then %y",
566 case WAIT_OBJECT_0
+ 1:
567 status
= STATUS_WAIT_1
;
570 case WAIT_OBJECT_0
+ 2:
571 status
= STATUS_THREAD_IS_TERMINATING
;
576 api_fatal ("WFMO failed, %E");
580 debug_printf ("NtFsControlFile status %y, no STATUS_PENDING",
586 if (fc
.get_state () != fc_listening
)
587 /* select.cc:peek_fifo has already recorded a connection. */
594 case STATUS_PIPE_CONNECTED
:
595 record_connection (fc
);
597 case STATUS_PIPE_CLOSING
:
598 debug_printf ("NtFsControlFile got STATUS_PIPE_CLOSING...");
599 /* Maybe a writer already connected, wrote, and closed.
600 Just query the O/S. */
601 fc
.query_and_set_state ();
602 debug_printf ("...O/S reports state %d", fc
.get_state ());
603 record_connection (fc
, false);
605 case STATUS_THREAD_IS_TERMINATING
:
607 /* Try to connect a bogus client. Otherwise fc is still
608 listening, and the next connection might not get recorded. */
609 status1
= open_pipe (ph
);
610 WaitForSingleObject (conn_evt
, INFINITE
);
611 if (NT_SUCCESS (status1
))
612 /* Bogus cilent connected. */
613 delete_client_handler (nhandlers
- 1);
615 /* Did a real client connect? */
619 case STATUS_PIPE_CONNECTED
:
620 record_connection (fc
);
622 case STATUS_PIPE_CLOSING
:
623 debug_printf ("got STATUS_PIPE_CLOSING when trying to connect bogus client...");
624 fc
.query_and_set_state ();
625 debug_printf ("...O/S reports state %d", fc
.get_state ());
626 record_connection (fc
, false);
629 debug_printf ("NtFsControlFile status %y after failing to connect bogus client or real client", io
.Status
);
630 fc
.set_state (fc_error
);
635 debug_printf ("NtFsControlFile got unexpected status %y", status
);
636 fc
.set_state (fc_error
);
645 if (get_owner () == me
&& update_shared_handlers () < 0)
646 api_fatal ("Can't update shared handlers, %E");
649 fifo_client_unlock ();
656 /* automatically return the cygthread to the cygthread pool */
657 _my_tls
._ctinfo
->auto_release ();
661 /* Return -1 on error and 0 or 1 on success. If ONLY_OPEN is true, we
662 expect the shared memory to exist, and we only try to open it. In
663 this case, we return 0 on success.
665 Otherwise, we create the shared memory if it doesn't exist, and we
666 return 1 if it already existed and we successfully open it. */
668 fhandler_fifo::create_shmem (bool only_open
)
671 OBJECT_ATTRIBUTES attr
;
672 NTSTATUS status
= STATUS_SUCCESS
;
673 LARGE_INTEGER size
= { .QuadPart
= sizeof (fifo_shmem_t
) };
674 SIZE_T viewsize
= sizeof (fifo_shmem_t
);
676 UNICODE_STRING uname
;
677 WCHAR shmem_name
[MAX_PATH
];
678 bool already_exists
= false;
680 __small_swprintf (shmem_name
, L
"fifo-shmem.%08x.%016X", get_dev (),
682 RtlInitUnicodeString (&uname
, shmem_name
);
683 InitializeObjectAttributes (&attr
, &uname
, OBJ_INHERIT
,
684 get_shared_parent_dir (), NULL
);
687 status
= NtCreateSection (§
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
688 | SECTION_MAP_READ
| SECTION_MAP_WRITE
,
689 &attr
, &size
, PAGE_READWRITE
, SEC_COMMIT
, NULL
);
690 if (status
== STATUS_OBJECT_NAME_COLLISION
)
691 already_exists
= true;
693 if (only_open
|| already_exists
)
694 status
= NtOpenSection (§
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
695 | SECTION_MAP_READ
| SECTION_MAP_WRITE
, &attr
);
696 if (!NT_SUCCESS (status
))
698 __seterrno_from_nt_status (status
);
701 status
= NtMapViewOfSection (sect
, NtCurrentProcess (), &addr
, 0, viewsize
,
702 NULL
, &viewsize
, ViewShare
, 0, PAGE_READWRITE
);
703 if (!NT_SUCCESS (status
))
706 __seterrno_from_nt_status (status
);
710 shmem
= (fifo_shmem_t
*) addr
;
711 return already_exists
? 1 : 0;
714 /* shmem_handle must be valid when this is called. */
716 fhandler_fifo::reopen_shmem ()
719 SIZE_T viewsize
= sizeof (fifo_shmem_t
);
722 status
= NtMapViewOfSection (shmem_handle
, NtCurrentProcess (), &addr
,
723 0, viewsize
, NULL
, &viewsize
, ViewShare
,
725 if (!NT_SUCCESS (status
))
727 __seterrno_from_nt_status (status
);
730 shmem
= (fifo_shmem_t
*) addr
;
734 /* On first creation, map and commit one page of memory. */
736 fhandler_fifo::create_shared_fc_handler ()
739 OBJECT_ATTRIBUTES attr
;
742 = { .QuadPart
= (LONGLONG
) (SH_FC_HANDLER_PAGES
* wincap
.page_size ()) };
743 SIZE_T viewsize
= get_shared_fc_handler_committed () ?: wincap
.page_size ();
745 UNICODE_STRING uname
;
746 WCHAR shared_fc_name
[MAX_PATH
];
748 __small_swprintf (shared_fc_name
, L
"fifo-shared-fc.%08x.%016X", get_dev (),
750 RtlInitUnicodeString (&uname
, shared_fc_name
);
751 InitializeObjectAttributes (&attr
, &uname
, OBJ_INHERIT
,
752 get_shared_parent_dir (), NULL
);
753 status
= NtCreateSection (§
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
754 | SECTION_MAP_READ
| SECTION_MAP_WRITE
, &attr
,
755 &size
, PAGE_READWRITE
, SEC_RESERVE
, NULL
);
756 if (status
== STATUS_OBJECT_NAME_COLLISION
)
757 status
= NtOpenSection (§
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
758 | SECTION_MAP_READ
| SECTION_MAP_WRITE
, &attr
);
759 if (!NT_SUCCESS (status
))
761 __seterrno_from_nt_status (status
);
764 status
= NtMapViewOfSection (sect
, NtCurrentProcess (), &addr
, 0, viewsize
,
765 NULL
, &viewsize
, ViewShare
, 0, PAGE_READWRITE
);
766 if (!NT_SUCCESS (status
))
769 __seterrno_from_nt_status (status
);
772 shared_fc_hdl
= sect
;
773 shared_fc_handler
= (fifo_client_handler
*) addr
;
774 if (!get_shared_fc_handler_committed ())
775 set_shared_fc_handler_committed (viewsize
);
776 set_shared_shandlers (viewsize
/ sizeof (fifo_client_handler
));
780 /* shared_fc_hdl must be valid when this is called. */
782 fhandler_fifo::reopen_shared_fc_handler ()
785 SIZE_T viewsize
= get_shared_fc_handler_committed ();
788 status
= NtMapViewOfSection (shared_fc_hdl
, NtCurrentProcess (),
789 &addr
, 0, viewsize
, NULL
, &viewsize
,
790 ViewShare
, 0, PAGE_READWRITE
);
791 if (!NT_SUCCESS (status
))
793 __seterrno_from_nt_status (status
);
796 shared_fc_handler
= (fifo_client_handler
*) addr
;
801 fhandler_fifo::remap_shared_fc_handler (size_t nbytes
)
804 SIZE_T viewsize
= roundup2 (nbytes
, wincap
.page_size ());
807 if (viewsize
> SH_FC_HANDLER_PAGES
* wincap
.page_size ())
813 NtUnmapViewOfSection (NtCurrentProcess (), shared_fc_handler
);
814 status
= NtMapViewOfSection (shared_fc_hdl
, NtCurrentProcess (),
815 &addr
, 0, viewsize
, NULL
, &viewsize
,
816 ViewShare
, 0, PAGE_READWRITE
);
817 if (!NT_SUCCESS (status
))
819 __seterrno_from_nt_status (status
);
822 shared_fc_handler
= (fifo_client_handler
*) addr
;
823 set_shared_fc_handler_committed (viewsize
);
824 set_shared_shandlers (viewsize
/ sizeof (fc_handler
[0]));
829 fhandler_fifo::open (int flags
, mode_t
)
831 int saved_errno
= 0, shmem_res
= 0;
834 return open_fs (flags
);
836 /* Determine what we're doing with this fhandler: reading, writing, both */
837 switch (flags
& O_ACCMODE
)
846 reader
= writer
= duplexer
= true;
853 debug_only_printf ("reader %d, writer %d, duplexer %d", reader
, writer
, duplexer
);
855 if (reader
&& !duplexer
)
858 /* Create control events for this named pipe */
859 char char_sa_buf
[1024];
860 LPSECURITY_ATTRIBUTES sa_buf
;
861 sa_buf
= sec_user_cloexec (flags
& O_CLOEXEC
, (PSECURITY_ATTRIBUTES
) char_sa_buf
,
862 cygheap
->user
.sid());
864 char npbuf
[MAX_PATH
];
865 __small_sprintf (npbuf
, "r-event.%08x.%016X", get_dev (), get_ino ());
866 if (!(read_ready
= CreateEvent (sa_buf
, true, false, npbuf
)))
868 debug_printf ("CreateEvent for %s failed, %E", npbuf
);
873 if (!(write_ready
= CreateEvent (sa_buf
, true, false, npbuf
)))
875 debug_printf ("CreateEvent for %s failed, %E", npbuf
);
877 goto err_close_read_ready
;
880 if (!(writer_opening
= CreateEvent (sa_buf
, true, false, npbuf
)))
882 debug_printf ("CreateEvent for %s failed, %E", npbuf
);
884 goto err_close_write_ready
;
887 /* If we're reading, create the shared memory and the shared
888 fc_handler memory, create some events, start the
889 fifo_reader_thread, signal read_ready, and wait for a writer. */
892 /* Create/open shared memory. */
893 if ((shmem_res
= create_shmem ()) < 0)
894 goto err_close_writer_opening
;
895 else if (shmem_res
== 0)
896 debug_printf ("shmem created");
898 debug_printf ("shmem existed; ok if we're not the first reader");
899 if (create_shared_fc_handler () < 0)
900 goto err_close_shmem
;
902 if (!(owner_needed_evt
= CreateEvent (sa_buf
, true, false, npbuf
)))
904 debug_printf ("CreateEvent for %s failed, %E", npbuf
);
906 goto err_close_shared_fc_handler
;
909 if (!(owner_found_evt
= CreateEvent (sa_buf
, true, false, npbuf
)))
911 debug_printf ("CreateEvent for %s failed, %E", npbuf
);
913 goto err_close_owner_needed_evt
;
916 if (!(update_needed_evt
= CreateEvent (sa_buf
, false, false, npbuf
)))
918 debug_printf ("CreateEvent for %s failed, %E", npbuf
);
920 goto err_close_owner_found_evt
;
922 if (!(cancel_evt
= create_event ()))
923 goto err_close_update_needed_evt
;
924 if (!(thr_sync_evt
= create_event ()))
925 goto err_close_cancel_evt
;
927 me
.winpid
= GetCurrentProcessId ();
930 if (inc_nreaders () == 1)
932 /* Reinitialize _sh_fc_handler_updated, which starts as 0. */
933 shared_fc_handler_updated (true);
936 new cygthread (fifo_reader_thread
, this, "fifo_reader", thr_sync_evt
);
937 SetEvent (read_ready
);
940 /* If we're a duplexer, we need a handle for writing. */
948 SetEvent (write_ready
);
953 status
= open_pipe (ph
);
954 if (NT_SUCCESS (status
))
957 set_pipe_non_blocking (ph
, flags
& O_NONBLOCK
);
960 else if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
962 /* The pipe hasn't been created yet. */
968 __seterrno_from_nt_status (status
);
970 goto err_close_reader
;
974 /* Not a duplexer; wait for a writer to connect if we're blocking. */
975 else if (!wait (write_ready
))
976 goto err_close_reader
;
980 /* If we're writing, wait for read_ready, connect to the pipe, open
981 the shared memory, and signal write_ready. */
986 /* Don't let a reader see EOF at this point. */
987 SetEvent (writer_opening
);
990 if (!wait (read_ready
))
992 ResetEvent (writer_opening
);
993 goto err_close_writer_opening
;
995 status
= open_pipe (get_handle ());
996 if (NT_SUCCESS (status
))
998 else if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1000 /* The pipe hasn't been created yet or there's no longer
1005 else if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status
))
1009 debug_printf ("create of writer failed");
1010 __seterrno_from_nt_status (status
);
1011 ResetEvent (writer_opening
);
1012 goto err_close_writer_opening
;
1016 /* We should get here only if the system is heavily loaded
1017 and/or many writers are trying to connect simultaneously */
1020 if (!wait (read_ready
))
1022 ResetEvent (writer_opening
);
1023 goto err_close_writer_opening
;
1025 status
= wait_open_pipe (get_handle ());
1026 if (NT_SUCCESS (status
))
1028 else if (status
== STATUS_IO_TIMEOUT
)
1032 debug_printf ("create of writer failed");
1033 __seterrno_from_nt_status (status
);
1034 ResetEvent (writer_opening
);
1035 goto err_close_writer_opening
;
1040 if (create_shmem (true) < 0)
1041 goto err_close_writer_opening
;
1042 /* writer_success: */
1043 set_pipe_non_blocking (get_handle (), flags
& O_NONBLOCK
);
1046 set_writer_opened ();
1047 SetEvent (write_ready
);
1048 ResetEvent (writer_opening
);
1053 __small_sprintf (npbuf
, "semaphore.%08x.%016X", get_dev (), get_ino ());
1054 select_sem
= CreateSemaphore (sa_buf
, 0, INT32_MAX
, npbuf
);
1058 saved_errno
= get_errno ();
1060 set_errno (saved_errno
);
1062 /* err_close_thr_sync_evt: */
1063 /* NtClose (thr_sync_evt); */
1064 err_close_cancel_evt
:
1065 NtClose (cancel_evt
);
1066 err_close_update_needed_evt
:
1067 NtClose (update_needed_evt
);
1068 err_close_owner_found_evt
:
1069 NtClose (owner_found_evt
);
1070 err_close_owner_needed_evt
:
1071 NtClose (owner_needed_evt
);
1072 err_close_shared_fc_handler
:
1073 NtUnmapViewOfSection (NtCurrentProcess (), shared_fc_handler
);
1074 NtClose (shared_fc_hdl
);
1076 NtUnmapViewOfSection (NtCurrentProcess (), shmem
);
1077 NtClose (shmem_handle
);
1078 err_close_writer_opening
:
1079 NtClose (writer_opening
);
1080 err_close_write_ready
:
1081 NtClose (write_ready
);
1082 err_close_read_ready
:
1083 NtClose (read_ready
);
1086 NtClose (get_handle ());
1091 fhandler_fifo::lseek (off_t offset
, int whence
)
1093 debug_printf ("(%D, %d)", offset
, whence
);
1099 fhandler_fifo::wait (HANDLE h
)
1103 if (h
== read_ready
)
1108 /* Set the wait to zero for non-blocking I/O-related events. */
1109 DWORD wait
= ((h
== read_ready
|| h
== write_ready
)
1110 && get_flags () & O_NONBLOCK
) ? 0 : INFINITE
;
1112 debug_only_printf ("waiting for %s", what
);
1113 /* Wait for the event. Set errno, as appropriate if something goes wrong. */
1114 switch (cygwait (h
, wait
))
1117 debug_only_printf ("successfully waited for %s", what
);
1120 debug_only_printf ("interrupted by signal while waiting for %s", what
);
1124 debug_only_printf ("cancellable interruption while waiting for %s", what
);
1125 pthread::static_cancel_self (); /* never returns */
1128 if (h
== write_ready
)
1130 debug_only_printf ("wait timed out waiting for write but will still open reader since non-blocking mode");
1140 debug_only_printf ("unknown error while waiting for %s", what
);
1146 /* Called from raw_read and select.cc:peek_fifo. */
1148 fhandler_fifo::take_ownership (DWORD timeout
)
1153 if (get_owner () == me
)
1158 set_pending_owner (me
);
1159 /* Wake up my fifo_reader_thread. */
1162 /* Wake up the owner and request an update of the shared fc_handlers. */
1163 SetEvent (update_needed_evt
);
1165 /* The reader threads should now do the transfer. */
1166 switch (WaitForSingleObject (owner_found_evt
, timeout
))
1170 if (get_owner () != me
)
1172 debug_printf ("owner_found_evt signaled, but I'm not the owner");
1178 debug_printf ("timed out");
1182 debug_printf ("WFSO failed, %E");
1190 fhandler_fifo::release_select_sem (const char *from
)
1193 if (reader
) /* Number of select() call. */
1194 n_release
= get_obj_handle_count (select_sem
)
1195 - get_obj_handle_count (read_ready
);
1196 else /* Number of select() and reader */
1197 n_release
= get_obj_handle_count (select_sem
)
1198 - get_obj_handle_count (get_handle ());
1199 debug_printf("%s(%s) release %d", from
,
1200 reader
? "reader" : "writer", n_release
);
1202 ReleaseSemaphore (select_sem
, n_release
, NULL
);
1205 /* Read from a non-blocking pipe and wait for completion. */
1207 nt_read (HANDLE h
, HANDLE evt
, PIO_STATUS_BLOCK pio
, void *in_ptr
, size_t& len
)
1212 status
= NtReadFile (h
, evt
, NULL
, NULL
, pio
, in_ptr
, len
, NULL
, NULL
);
1213 if (status
== STATUS_PENDING
)
1215 /* Very short-lived */
1216 status
= NtWaitForSingleObject (evt
, FALSE
, NULL
);
1217 if (NT_SUCCESS (status
))
1218 status
= pio
->Status
;
1224 fhandler_fifo::raw_read (void *in_ptr
, size_t& len
)
1231 if (!(evt
= CreateEvent (NULL
, false, false, NULL
)))
1242 /* No one else can take ownership while we hold the reading_lock. */
1244 if (take_ownership (10) < 0)
1247 fifo_client_lock ();
1248 /* Poll the connected clients for input. Make three passes.
1250 On the first pass, just try to read from the client from
1251 which we last read successfully. This should minimize
1252 interleaving of writes from different clients.
1254 On the second pass, just try to read from the clients in the
1255 state fc_input_avail. This should be more efficient if
1256 select has been called and detected input available.
1258 On the third pass, try to read from all connected clients. */
1262 for (j
= 0; j
< nhandlers
; j
++)
1263 if (fc_handler
[j
].last_read
)
1265 if (j
< nhandlers
&& fc_handler
[j
].get_state () < fc_connected
)
1267 fc_handler
[j
].last_read
= false;
1275 status
= nt_read (fc_handler
[j
].h
, evt
, &io
, in_ptr
, len
);
1278 case STATUS_SUCCESS
:
1279 case STATUS_BUFFER_OVERFLOW
:
1280 if (io
.Information
> 0)
1282 len
= io
.Information
;
1286 case STATUS_PIPE_EMPTY
:
1287 /* Update state in case it's fc_input_avail. */
1288 fc_handler
[j
].set_state (fc_connected
);
1290 case STATUS_PIPE_BROKEN
:
1291 fc_handler
[j
].set_state (fc_disconnected
);
1294 debug_printf ("nt_read status %y", status
);
1295 fc_handler
[j
].set_state (fc_error
);
1301 for (int i
= 0; i
< nhandlers
; i
++)
1302 if (fc_handler
[i
].get_state () == fc_input_avail
)
1307 status
= nt_read (fc_handler
[i
].h
, evt
, &io
, in_ptr
, len
);
1310 case STATUS_SUCCESS
:
1311 case STATUS_BUFFER_OVERFLOW
:
1312 if (io
.Information
> 0)
1314 len
= io
.Information
;
1316 fc_handler
[j
].last_read
= false;
1317 fc_handler
[i
].last_read
= true;
1321 case STATUS_PIPE_EMPTY
:
1322 /* No input available after all. */
1323 fc_handler
[i
].set_state (fc_connected
);
1325 case STATUS_PIPE_BROKEN
:
1326 fc_handler
[i
].set_state (fc_disconnected
);
1329 debug_printf ("nt_read status %y", status
);
1330 fc_handler
[i
].set_state (fc_error
);
1336 for (int i
= 0; i
< nhandlers
; i
++)
1337 if (fc_handler
[i
].get_state () >= fc_connected
)
1343 status
= nt_read (fc_handler
[i
].h
, evt
, &io
, in_ptr
, len
);
1346 case STATUS_SUCCESS
:
1347 case STATUS_BUFFER_OVERFLOW
:
1348 if (io
.Information
> 0)
1350 len
= io
.Information
;
1352 fc_handler
[j
].last_read
= false;
1353 fc_handler
[i
].last_read
= true;
1357 case STATUS_PIPE_EMPTY
:
1359 case STATUS_PIPE_BROKEN
:
1360 fc_handler
[i
].set_state (fc_disconnected
);
1364 debug_printf ("nt_read status %y", status
);
1365 fc_handler
[i
].set_state (fc_error
);
1370 if (!nconnected
&& hit_eof ())
1375 fifo_client_unlock ();
1378 if (is_nonblocking ())
1386 /* Allow interruption and don't hog the CPU. */
1387 DWORD waitret
= cygwait (select_sem
, 1, cw_cancel
| cw_sig_eintr
);
1388 if (waitret
== WAIT_CANCELED
)
1389 pthread::static_cancel_self ();
1390 else if (waitret
== WAIT_SIGNALED
)
1392 if (_my_tls
.call_signal_handler ())
1402 /* We might have been closed by a signal handler or another thread. */
1411 fifo_client_unlock ();
1415 release_select_sem ("raw_read");
1420 fhandler_fifo::fstat (struct stat
*buf
)
1422 if (reader
|| writer
|| duplexer
)
1424 /* fhandler_fifo::open has been called, and O_PATH is not set.
1425 We don't want to call fhandler_base::fstat. In the writer
1426 and duplexer cases we have a handle, but it's a pipe handle
1427 rather than a file handle, so it's not suitable for stat. In
1428 the reader case we don't have a handle, but
1429 fhandler_base::fstat would call fhandler_base::open, which
1430 would modify the flags and status_flags. */
1431 fhandler_disk_file
fh (pc
);
1432 fh
.get_device () = FH_FS
;
1433 int res
= fh
.fstat (buf
);
1434 buf
->st_dev
= buf
->st_rdev
= dev ();
1435 buf
->st_mode
= dev ().mode ();
1439 return fhandler_base::fstat (buf
);
1443 fhandler_fifo::fstatvfs (struct statvfs
*sfs
)
1445 if (get_flags () & O_PATH
)
1446 /* We already have a handle. */
1448 HANDLE h
= get_handle ();
1450 return fstatvfs_by_handle (h
, sfs
);
1453 fhandler_disk_file
fh (pc
);
1454 fh
.get_device () = FH_FS
;
1455 return fh
.fstatvfs (sfs
);
1459 fhandler_fifo::close_all_handlers ()
1461 fifo_client_lock ();
1462 for (int i
= 0; i
< nhandlers
; i
++)
1463 fc_handler
[i
].close ();
1465 fifo_client_unlock ();
1468 /* Return previous state. */
1469 fifo_client_connect_state
1470 fifo_client_handler::query_and_set_state ()
1473 FILE_PIPE_LOCAL_INFORMATION fpli
;
1475 fifo_client_connect_state prev_state
= get_state ();
1479 set_state (fc_unknown
);
1483 status
= NtQueryInformationFile (h
, &io
, &fpli
,
1484 sizeof (fpli
), FilePipeLocalInformation
);
1485 if (!NT_SUCCESS (status
))
1487 debug_printf ("NtQueryInformationFile status %y", status
);
1488 set_state (fc_error
);
1490 else if (fpli
.ReadDataAvailable
> 0)
1491 set_state (fc_input_avail
);
1493 switch (fpli
.NamedPipeState
)
1495 case FILE_PIPE_DISCONNECTED_STATE
:
1496 set_state (fc_disconnected
);
1498 case FILE_PIPE_LISTENING_STATE
:
1499 set_state (fc_listening
);
1501 case FILE_PIPE_CONNECTED_STATE
:
1502 set_state (fc_connected
);
1504 case FILE_PIPE_CLOSING_STATE
:
1505 set_state (fc_closing
);
1508 set_state (fc_error
);
1516 fhandler_fifo::cancel_reader_thread ()
1519 SetEvent (cancel_evt
);
1521 WaitForSingleObject (thr_sync_evt
, INFINITE
);
1525 fhandler_fifo::close ()
1529 release_select_sem ("close");
1530 NtClose (select_sem
);
1535 if (dec_nwriters () == 0)
1536 ResetEvent (write_ready
);
1541 /* If we're the owner, we can't close our fc_handlers if a new
1542 owner might need to duplicate them. */
1543 bool close_fc_ok
= false;
1545 cancel_reader_thread ();
1547 if (dec_nreaders () == 0)
1550 ResetEvent (read_ready
);
1551 ResetEvent (owner_needed_evt
);
1552 ResetEvent (owner_found_evt
);
1553 set_owner (null_fr_id
);
1554 set_prev_owner (null_fr_id
);
1555 set_pending_owner (null_fr_id
);
1556 set_shared_nhandlers (0);
1561 if (get_owner () != me
)
1565 set_owner (null_fr_id
);
1566 set_prev_owner (me
);
1567 if (!get_pending_owner ())
1573 while (!close_fc_ok
)
1575 if (WaitForSingleObject (owner_found_evt
, 1) == WAIT_OBJECT_0
)
1589 if (get_owner () || get_prev_owner () != me
)
1595 close_all_handlers ();
1598 if (owner_needed_evt
)
1599 NtClose (owner_needed_evt
);
1600 if (owner_found_evt
)
1601 NtClose (owner_found_evt
);
1602 if (update_needed_evt
)
1603 NtClose (update_needed_evt
);
1605 NtClose (cancel_evt
);
1607 NtClose (thr_sync_evt
);
1608 if (shared_fc_handler
)
1609 NtUnmapViewOfSection (NtCurrentProcess (), shared_fc_handler
);
1611 NtClose (shared_fc_hdl
);
1614 NtUnmapViewOfSection (NtCurrentProcess (), shmem
);
1616 NtClose (shmem_handle
);
1618 NtClose (read_ready
);
1620 NtClose (write_ready
);
1622 NtClose (writer_opening
);
1626 return fhandler_base::close ();
1629 /* If we have a write handle (i.e., we're a duplexer or a writer),
1630 keep the nonblocking state of the windows pipe in sync with our
1631 nonblocking state. */
1633 fhandler_fifo::fcntl (int cmd
, intptr_t arg
)
1635 if (cmd
!= F_SETFL
|| nohandle () || (get_flags () & O_PATH
))
1636 return fhandler_base::fcntl (cmd
, arg
);
1638 const bool was_nonblocking
= is_nonblocking ();
1639 int res
= fhandler_base::fcntl (cmd
, arg
);
1640 const bool now_nonblocking
= is_nonblocking ();
1641 if (now_nonblocking
!= was_nonblocking
)
1642 set_pipe_non_blocking (get_handle (), now_nonblocking
);
1647 fhandler_fifo::dup (fhandler_base
*child
, int flags
)
1649 fhandler_fifo
*fhf
= NULL
;
1651 if (get_flags () & O_PATH
)
1652 return fhandler_base::dup (child
, flags
);
1654 if (fhandler_base::dup (child
, flags
))
1657 fhf
= (fhandler_fifo
*) child
;
1658 if (!DuplicateHandle (GetCurrentProcess (), read_ready
,
1659 GetCurrentProcess (), &fhf
->read_ready
,
1660 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1665 if (!DuplicateHandle (GetCurrentProcess (), write_ready
,
1666 GetCurrentProcess (), &fhf
->write_ready
,
1667 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1670 goto err_close_read_ready
;
1672 if (!DuplicateHandle (GetCurrentProcess (), writer_opening
,
1673 GetCurrentProcess (), &fhf
->writer_opening
,
1674 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1677 goto err_close_write_ready
;
1679 if (!DuplicateHandle (GetCurrentProcess (), shmem_handle
,
1680 GetCurrentProcess (), &fhf
->shmem_handle
,
1681 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1684 goto err_close_writer_opening
;
1686 if (fhf
->reopen_shmem () < 0)
1687 goto err_close_shmem_handle
;
1689 !DuplicateHandle (GetCurrentProcess (), select_sem
,
1690 GetCurrentProcess (), &fhf
->select_sem
,
1691 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1694 goto err_close_shmem
;
1698 /* Make sure the child starts unlocked. */
1699 fhf
->fifo_client_unlock ();
1701 /* Clear fc_handler list; the child never starts as owner. */
1702 fhf
->nhandlers
= fhf
->shandlers
= 0;
1703 fhf
->fc_handler
= NULL
;
1705 if (!DuplicateHandle (GetCurrentProcess (), shared_fc_hdl
,
1706 GetCurrentProcess (), &fhf
->shared_fc_hdl
,
1707 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1710 goto err_close_select_sem
;
1712 if (fhf
->reopen_shared_fc_handler () < 0)
1713 goto err_close_shared_fc_hdl
;
1714 if (!DuplicateHandle (GetCurrentProcess (), owner_needed_evt
,
1715 GetCurrentProcess (), &fhf
->owner_needed_evt
,
1716 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1719 goto err_close_shared_fc_handler
;
1721 if (!DuplicateHandle (GetCurrentProcess (), owner_found_evt
,
1722 GetCurrentProcess (), &fhf
->owner_found_evt
,
1723 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1726 goto err_close_owner_needed_evt
;
1728 if (!DuplicateHandle (GetCurrentProcess (), update_needed_evt
,
1729 GetCurrentProcess (), &fhf
->update_needed_evt
,
1730 0, !(flags
& O_CLOEXEC
), DUPLICATE_SAME_ACCESS
))
1733 goto err_close_owner_found_evt
;
1735 if (!(fhf
->cancel_evt
= create_event ()))
1736 goto err_close_update_needed_evt
;
1737 if (!(fhf
->thr_sync_evt
= create_event ()))
1738 goto err_close_cancel_evt
;
1741 new cygthread (fifo_reader_thread
, fhf
, "fifo_reader", fhf
->thr_sync_evt
);
1746 err_close_cancel_evt
:
1747 NtClose (fhf
->cancel_evt
);
1748 err_close_update_needed_evt
:
1749 NtClose (fhf
->update_needed_evt
);
1750 err_close_owner_found_evt
:
1751 NtClose (fhf
->owner_found_evt
);
1752 err_close_owner_needed_evt
:
1753 NtClose (fhf
->owner_needed_evt
);
1754 err_close_shared_fc_handler
:
1755 NtUnmapViewOfSection (GetCurrentProcess (), fhf
->shared_fc_handler
);
1756 err_close_shared_fc_hdl
:
1757 NtClose (fhf
->shared_fc_hdl
);
1758 err_close_select_sem
:
1759 NtClose (fhf
->select_sem
);
1761 NtUnmapViewOfSection (GetCurrentProcess (), fhf
->shmem
);
1762 err_close_shmem_handle
:
1763 NtClose (fhf
->shmem_handle
);
1764 err_close_writer_opening
:
1765 NtClose (fhf
->writer_opening
);
1766 err_close_write_ready
:
1767 NtClose (fhf
->write_ready
);
1768 err_close_read_ready
:
1769 NtClose (fhf
->read_ready
);
1775 fhandler_fifo::fixup_after_fork (HANDLE parent
)
1777 fhandler_base::fixup_after_fork (parent
);
1778 fork_fixup (parent
, read_ready
, "read_ready");
1779 fork_fixup (parent
, write_ready
, "write_ready");
1780 fork_fixup (parent
, writer_opening
, "writer_opening");
1781 fork_fixup (parent
, shmem_handle
, "shmem_handle");
1782 if (reopen_shmem () < 0)
1783 api_fatal ("Can't reopen shared memory during fork, %E");
1785 fork_fixup (parent
, select_sem
, "select_sem");
1788 /* Make sure the child starts unlocked. */
1789 fifo_client_unlock ();
1791 fork_fixup (parent
, shared_fc_hdl
, "shared_fc_hdl");
1792 if (reopen_shared_fc_handler () < 0)
1793 api_fatal ("Can't reopen shared fc_handler memory during fork, %E");
1794 fork_fixup (parent
, owner_needed_evt
, "owner_needed_evt");
1795 fork_fixup (parent
, owner_found_evt
, "owner_found_evt");
1796 fork_fixup (parent
, update_needed_evt
, "update_needed_evt");
1797 if (close_on_exec ())
1798 /* Prevent a later attempt to close the non-inherited
1799 pipe-instance handles copied from the parent. */
1801 if (!(cancel_evt
= create_event ()))
1802 api_fatal ("Can't create reader thread cancel event during fork, %E");
1803 if (!(thr_sync_evt
= create_event ()))
1804 api_fatal ("Can't create reader thread sync event during fork, %E");
1806 me
.winpid
= GetCurrentProcessId ();
1807 new cygthread (fifo_reader_thread
, this, "fifo_reader", thr_sync_evt
);
1814 fhandler_fifo::fixup_after_exec ()
1816 fhandler_base::fixup_after_exec ();
1817 if (close_on_exec ())
1819 if (reopen_shmem () < 0)
1820 api_fatal ("Can't reopen shared memory during exec, %E");
1823 /* Make sure the child starts unlocked. */
1824 fifo_client_unlock ();
1826 if (reopen_shared_fc_handler () < 0)
1827 api_fatal ("Can't reopen shared fc_handler memory during exec, %E");
1829 nhandlers
= shandlers
= 0;
1830 if (!(cancel_evt
= create_event ()))
1831 api_fatal ("Can't create reader thread cancel event during exec, %E");
1832 if (!(thr_sync_evt
= create_event ()))
1833 api_fatal ("Can't create reader thread sync event during exec, %E");
1834 /* At this moment we're a new reader. The count will be
1835 decremented when the parent closes. */
1837 me
.winpid
= GetCurrentProcessId ();
1838 new cygthread (fifo_reader_thread
, this, "fifo_reader", thr_sync_evt
);
1845 fhandler_fifo::set_close_on_exec (bool val
)
1847 fhandler_base::set_close_on_exec (val
);
1848 set_no_inheritance (read_ready
, val
);
1849 set_no_inheritance (write_ready
, val
);
1850 set_no_inheritance (writer_opening
, val
);
1853 set_no_inheritance (owner_needed_evt
, val
);
1854 set_no_inheritance (owner_found_evt
, val
);
1855 set_no_inheritance (update_needed_evt
, val
);
1856 fifo_client_lock ();
1857 for (int i
= 0; i
< nhandlers
; i
++)
1858 set_no_inheritance (fc_handler
[i
].h
, val
);
1859 fifo_client_unlock ();
1862 set_no_inheritance (select_sem
, val
);