2005-04-16 07:20:01 +02:00
|
|
|
/* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes.
|
2003-09-20 02:31:13 +02:00
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
#include "winsup.h"
|
2019-03-22 20:30:36 +01:00
|
|
|
#include <w32api/winioctl.h>
|
2008-04-07 18:15:45 +02:00
|
|
|
#include "miscfuncs.h"
|
2003-09-20 02:31:13 +02:00
|
|
|
|
|
|
|
#include "cygerrno.h"
|
|
|
|
#include "security.h"
|
|
|
|
#include "path.h"
|
|
|
|
#include "fhandler.h"
|
|
|
|
#include "dtable.h"
|
|
|
|
#include "cygheap.h"
|
2007-07-07 19:00:33 +02:00
|
|
|
#include "sigproc.h"
|
|
|
|
#include "cygtls.h"
|
2009-10-31 14:24:06 +01:00
|
|
|
#include "shared_info.h"
|
2011-04-29 10:27:11 +02:00
|
|
|
#include "ntdll.h"
|
2012-06-17 22:50:24 +02:00
|
|
|
#include "cygwait.h"
|
2003-09-20 02:31:13 +02:00
|
|
|
|
2020-02-01 22:36:31 +01:00
|
|
|
/*
|
|
|
|
Overview:
|
|
|
|
|
|
|
|
Currently a FIFO can be opened once for reading and multiple
|
|
|
|
times for writing. Any attempt to open the FIFO a second time
|
|
|
|
for reading fails with EACCES (from STATUS_ACCESS_DENIED).
|
|
|
|
|
|
|
|
When a FIFO is opened for reading,
|
|
|
|
fhandler_fifo::create_pipe_instance is called to create the first
|
|
|
|
instance of a Windows named pipe server (Windows terminology). A
|
2020-03-26 19:29:50 +01:00
|
|
|
"fifo_reader" thread is also started; it waits for pipe clients
|
2020-02-01 22:36:31 +01:00
|
|
|
(Windows terminology again) to connect. This happens every time
|
|
|
|
a process opens the FIFO for writing.
|
|
|
|
|
2020-03-26 19:29:50 +01:00
|
|
|
The fifo_reader thread creates new instances of the pipe server
|
2020-02-01 22:36:31 +01:00
|
|
|
as needed, so that there is always an instance available for a
|
|
|
|
writer to connect to.
|
|
|
|
|
|
|
|
The reader maintains a list of "fifo_client_handlers", one for
|
|
|
|
each pipe instance. A fifo_client_handler manages the connection
|
|
|
|
between the pipe instance and a writer connected to that pipe
|
|
|
|
instance.
|
|
|
|
|
|
|
|
TODO: Allow a FIFO to be opened multiple times for reading.
|
|
|
|
Maybe this could be done by using shared memory, so that all
|
|
|
|
readers could have access to the same list of writers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
/* This is only to be used for writers. When reading,
|
|
|
|
STATUS_PIPE_EMPTY simply means there's no data to be read. */
|
|
|
|
#define STATUS_PIPE_IS_CLOSED(status) \
|
|
|
|
({ NTSTATUS _s = (status); \
|
|
|
|
_s == STATUS_PIPE_CLOSING \
|
|
|
|
|| _s == STATUS_PIPE_BROKEN \
|
|
|
|
|| _s == STATUS_PIPE_EMPTY; })
|
|
|
|
|
2019-04-14 21:16:02 +02:00
|
|
|
#define STATUS_PIPE_NO_INSTANCE_AVAILABLE(status) \
|
|
|
|
({ NTSTATUS _s = (status); \
|
|
|
|
_s == STATUS_INSTANCE_NOT_AVAILABLE \
|
|
|
|
|| _s == STATUS_PIPE_NOT_AVAILABLE \
|
|
|
|
|| _s == STATUS_PIPE_BUSY; })
|
|
|
|
|
2020-03-26 00:22:10 +01:00
|
|
|
static NO_COPY fifo_reader_id_t null_fr_id = { .winpid = 0, .fh = NULL };
|
|
|
|
|
2007-07-07 19:00:33 +02:00
|
|
|
fhandler_fifo::fhandler_fifo ():
|
2020-04-26 15:38:46 +02:00
|
|
|
fhandler_base (),
|
|
|
|
read_ready (NULL), write_ready (NULL), writer_opening (NULL),
|
2020-03-26 19:29:50 +01:00
|
|
|
cancel_evt (NULL), thr_sync_evt (NULL), _maybe_eof (false), nhandlers (0),
|
2020-04-26 15:38:46 +02:00
|
|
|
reader (false), writer (false), duplexer (false),
|
2020-03-17 17:29:56 +01:00
|
|
|
max_atomic_write (DEFAULT_PIPEBUFSIZE),
|
2020-03-26 00:22:10 +01:00
|
|
|
me (null_fr_id), shmem_handle (NULL), shmem (NULL)
|
2003-09-20 02:31:13 +02:00
|
|
|
{
|
2019-03-22 20:30:36 +01:00
|
|
|
pipe_name_buf[0] = L'\0';
|
2007-07-07 19:00:33 +02:00
|
|
|
need_fork_fixup (true);
|
2003-09-20 02:31:13 +02:00
|
|
|
}
|
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
PUNICODE_STRING
|
|
|
|
fhandler_fifo::get_pipe_name ()
|
2009-07-24 22:54:33 +02:00
|
|
|
{
|
2019-03-22 20:30:36 +01:00
|
|
|
if (!pipe_name_buf[0])
|
|
|
|
{
|
|
|
|
__small_swprintf (pipe_name_buf, L"%S-fifo.%08x.%016X",
|
|
|
|
&cygheap->installation_key, get_dev (), get_ino ());
|
|
|
|
RtlInitUnicodeString (&pipe_name, pipe_name_buf);
|
|
|
|
}
|
|
|
|
return &pipe_name;
|
2009-07-24 22:54:33 +02:00
|
|
|
}
|
|
|
|
|
2010-01-14 19:46:02 +01:00
|
|
|
inline PSECURITY_ATTRIBUTES
|
|
|
|
sec_user_cloexec (bool cloexec, PSECURITY_ATTRIBUTES sa, PSID sid)
|
|
|
|
{
|
|
|
|
return cloexec ? sec_user_nih (sa, sid) : sec_user (sa, sid);
|
|
|
|
}
|
2005-04-22 15:58:09 +02:00
|
|
|
|
2019-03-22 20:30:37 +01:00
|
|
|
static HANDLE
|
|
|
|
create_event ()
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
OBJECT_ATTRIBUTES attr;
|
|
|
|
HANDLE evt = NULL;
|
|
|
|
|
|
|
|
InitializeObjectAttributes (&attr, NULL, 0, NULL, NULL);
|
|
|
|
status = NtCreateEvent (&evt, EVENT_ALL_ACCESS, &attr,
|
|
|
|
NotificationEvent, FALSE);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
return evt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_pipe_non_blocking (HANDLE ph, bool nonblocking)
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
FILE_PIPE_INFORMATION fpi;
|
|
|
|
|
|
|
|
fpi.ReadMode = FILE_PIPE_MESSAGE_MODE;
|
|
|
|
fpi.CompletionMode = nonblocking ? FILE_PIPE_COMPLETE_OPERATION
|
|
|
|
: FILE_PIPE_QUEUE_OPERATION;
|
|
|
|
status = NtSetInformationFile (ph, &io, &fpi, sizeof fpi,
|
|
|
|
FilePipeInformation);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status);
|
|
|
|
}
|
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
NTSTATUS
|
|
|
|
fhandler_fifo::npfs_handle (HANDLE &nph)
|
|
|
|
{
|
|
|
|
static NO_COPY SRWLOCK npfs_lock;
|
|
|
|
static NO_COPY HANDLE npfs_dirh;
|
|
|
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
OBJECT_ATTRIBUTES attr;
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
|
|
|
|
/* Lockless after first call. */
|
|
|
|
if (npfs_dirh)
|
|
|
|
{
|
|
|
|
nph = npfs_dirh;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
AcquireSRWLockExclusive (&npfs_lock);
|
|
|
|
if (!npfs_dirh)
|
|
|
|
{
|
|
|
|
InitializeObjectAttributes (&attr, &ro_u_npfs, 0, NULL, NULL);
|
|
|
|
status = NtOpenFile (&npfs_dirh, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
|
|
|
&attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
ReleaseSRWLockExclusive (&npfs_lock);
|
|
|
|
if (NT_SUCCESS (status))
|
|
|
|
nph = npfs_dirh;
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2019-03-22 20:30:37 +01:00
|
|
|
/* Called when a FIFO is first opened for reading and again each time
|
2019-04-14 21:15:56 +02:00
|
|
|
a new client handler is needed. Each pipe instance is created in
|
|
|
|
blocking mode so that we can easily wait for a connection. After
|
|
|
|
it is connected, it is put in nonblocking mode. */
|
2019-03-22 20:30:36 +01:00
|
|
|
HANDLE
|
2019-03-22 20:30:37 +01:00
|
|
|
fhandler_fifo::create_pipe_instance (bool first)
|
2019-03-22 20:30:36 +01:00
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
HANDLE npfsh;
|
|
|
|
HANDLE ph = NULL;
|
|
|
|
ACCESS_MASK access;
|
|
|
|
OBJECT_ATTRIBUTES attr;
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
ULONG hattr;
|
|
|
|
ULONG sharing;
|
|
|
|
ULONG nonblocking = FILE_PIPE_QUEUE_OPERATION;
|
2019-03-22 20:30:37 +01:00
|
|
|
ULONG max_instances = -1;
|
2019-03-22 20:30:36 +01:00
|
|
|
LARGE_INTEGER timeout;
|
|
|
|
|
|
|
|
status = npfs_handle (npfsh);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
{
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
access = GENERIC_READ | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES
|
|
|
|
| SYNCHRONIZE;
|
|
|
|
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
2019-05-28 21:50:05 +02:00
|
|
|
hattr = openflags & O_CLOEXEC ? 0 : OBJ_INHERIT;
|
2019-03-22 20:30:37 +01:00
|
|
|
if (first)
|
|
|
|
hattr |= OBJ_CASE_INSENSITIVE;
|
2019-03-22 20:30:36 +01:00
|
|
|
InitializeObjectAttributes (&attr, get_pipe_name (),
|
|
|
|
hattr, npfsh, NULL);
|
|
|
|
timeout.QuadPart = -500000;
|
|
|
|
status = NtCreateNamedPipeFile (&ph, access, &attr, &io, sharing,
|
2019-03-22 20:30:37 +01:00
|
|
|
first ? FILE_CREATE : FILE_OPEN, 0,
|
2019-12-21 23:53:52 +01:00
|
|
|
FILE_PIPE_MESSAGE_TYPE
|
|
|
|
| FILE_PIPE_REJECT_REMOTE_CLIENTS,
|
2019-03-22 20:30:36 +01:00
|
|
|
FILE_PIPE_MESSAGE_MODE,
|
|
|
|
nonblocking, max_instances,
|
|
|
|
DEFAULT_PIPEBUFSIZE, DEFAULT_PIPEBUFSIZE,
|
|
|
|
&timeout);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
return ph;
|
|
|
|
}
|
|
|
|
|
2019-05-09 17:36:26 +02:00
|
|
|
/* Connect to a pipe instance. */
|
2019-03-22 20:30:36 +01:00
|
|
|
NTSTATUS
|
2019-05-09 17:36:26 +02:00
|
|
|
fhandler_fifo::open_pipe (HANDLE& ph)
|
2019-03-22 20:30:36 +01:00
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
HANDLE npfsh;
|
|
|
|
ACCESS_MASK access;
|
|
|
|
OBJECT_ATTRIBUTES attr;
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
ULONG sharing;
|
|
|
|
|
|
|
|
status = npfs_handle (npfsh);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
return status;
|
|
|
|
access = GENERIC_WRITE | SYNCHRONIZE;
|
2019-05-28 21:50:05 +02:00
|
|
|
InitializeObjectAttributes (&attr, get_pipe_name (),
|
|
|
|
openflags & O_CLOEXEC ? 0 : OBJ_INHERIT,
|
2019-03-22 20:30:36 +01:00
|
|
|
npfsh, NULL);
|
|
|
|
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
2020-03-17 19:14:47 +01:00
|
|
|
return NtOpenFile (&ph, access, &attr, &io, sharing, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait up to 100ms for a pipe instance to be available, then connect. */
|
|
|
|
NTSTATUS
|
|
|
|
fhandler_fifo::wait_open_pipe (HANDLE& ph)
|
|
|
|
{
|
|
|
|
HANDLE npfsh;
|
|
|
|
HANDLE evt;
|
|
|
|
NTSTATUS status;
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
ULONG pwbuf_size;
|
|
|
|
PFILE_PIPE_WAIT_FOR_BUFFER pwbuf;
|
|
|
|
LONGLONG stamp;
|
|
|
|
LONGLONG orig_timeout = -100 * NS100PERSEC / MSPERSEC; /* 100ms */
|
|
|
|
|
|
|
|
status = npfs_handle (npfsh);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
return status;
|
|
|
|
if (!(evt = create_event ()))
|
|
|
|
api_fatal ("Can't create event, %E");
|
|
|
|
pwbuf_size
|
|
|
|
= offsetof (FILE_PIPE_WAIT_FOR_BUFFER, Name) + get_pipe_name ()->Length;
|
|
|
|
pwbuf = (PFILE_PIPE_WAIT_FOR_BUFFER) alloca (pwbuf_size);
|
|
|
|
pwbuf->Timeout.QuadPart = orig_timeout;
|
|
|
|
pwbuf->NameLength = get_pipe_name ()->Length;
|
|
|
|
pwbuf->TimeoutSpecified = TRUE;
|
|
|
|
memcpy (pwbuf->Name, get_pipe_name ()->Buffer, get_pipe_name ()->Length);
|
|
|
|
stamp = get_clock (CLOCK_MONOTONIC)->n100secs ();
|
|
|
|
bool retry;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
retry = false;
|
|
|
|
status = NtFsControlFile (npfsh, evt, NULL, NULL, &io, FSCTL_PIPE_WAIT,
|
|
|
|
pwbuf, pwbuf_size, NULL, 0);
|
|
|
|
if (status == STATUS_PENDING)
|
|
|
|
{
|
|
|
|
if (WaitForSingleObject (evt, INFINITE) == WAIT_OBJECT_0)
|
|
|
|
status = io.Status;
|
|
|
|
else
|
|
|
|
api_fatal ("WFSO failed, %E");
|
|
|
|
}
|
|
|
|
if (NT_SUCCESS (status))
|
|
|
|
status = open_pipe (ph);
|
|
|
|
if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status))
|
|
|
|
{
|
|
|
|
/* Another writer has grabbed the pipe instance. Adjust
|
|
|
|
the timeout and keep waiting if there's time left. */
|
|
|
|
pwbuf->Timeout.QuadPart = orig_timeout
|
|
|
|
+ get_clock (CLOCK_MONOTONIC)->n100secs () - stamp;
|
|
|
|
if (pwbuf->Timeout.QuadPart < 0)
|
|
|
|
retry = true;
|
|
|
|
else
|
|
|
|
status = STATUS_IO_TIMEOUT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (retry);
|
|
|
|
NtClose (evt);
|
2019-03-22 20:30:36 +01:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2019-03-22 20:30:37 +01:00
|
|
|
int
|
2019-04-14 21:15:56 +02:00
|
|
|
fhandler_fifo::add_client_handler ()
|
2019-03-22 20:30:37 +01:00
|
|
|
{
|
2019-04-14 21:16:04 +02:00
|
|
|
int ret = -1;
|
2019-03-22 20:30:37 +01:00
|
|
|
fifo_client_handler fc;
|
2019-04-14 21:16:04 +02:00
|
|
|
HANDLE ph = NULL;
|
2019-04-14 21:15:56 +02:00
|
|
|
bool first = (nhandlers == 0);
|
2019-03-22 20:30:37 +01:00
|
|
|
|
2019-04-14 21:15:56 +02:00
|
|
|
if (nhandlers == MAX_CLIENTS)
|
2019-03-22 20:30:37 +01:00
|
|
|
{
|
|
|
|
set_errno (EMFILE);
|
2019-04-14 21:16:04 +02:00
|
|
|
goto out;
|
2019-03-22 20:30:37 +01:00
|
|
|
}
|
2019-04-14 21:16:04 +02:00
|
|
|
ph = create_pipe_instance (first);
|
2019-03-22 20:30:37 +01:00
|
|
|
if (!ph)
|
2020-03-16 23:04:28 +01:00
|
|
|
goto out;
|
2019-04-14 21:16:04 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = 0;
|
2020-03-16 23:04:28 +01:00
|
|
|
fc.h = ph;
|
2020-05-07 00:39:26 +02:00
|
|
|
fc.state = fc_listening;
|
2019-04-14 21:16:04 +02:00
|
|
|
fc_handler[nhandlers++] = fc;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
2019-03-22 20:30:37 +01:00
|
|
|
|
2020-03-16 23:04:28 +01:00
|
|
|
void
|
2019-04-14 21:16:04 +02:00
|
|
|
fhandler_fifo::delete_client_handler (int i)
|
|
|
|
{
|
2020-03-16 23:04:28 +01:00
|
|
|
fc_handler[i].close ();
|
2019-04-14 21:16:04 +02:00
|
|
|
if (i < --nhandlers)
|
|
|
|
memmove (fc_handler + i, fc_handler + i + 1,
|
|
|
|
(nhandlers - i) * sizeof (fc_handler[i]));
|
2019-03-22 20:30:37 +01:00
|
|
|
}
|
|
|
|
|
2019-05-09 16:58:29 +02:00
|
|
|
void
|
2020-05-07 00:39:26 +02:00
|
|
|
fhandler_fifo::record_connection (fifo_client_handler& fc,
|
|
|
|
fifo_client_connect_state s)
|
2019-05-09 16:58:29 +02:00
|
|
|
{
|
2020-05-07 00:39:26 +02:00
|
|
|
fc.state = s;
|
2020-04-26 15:38:46 +02:00
|
|
|
maybe_eof (false);
|
|
|
|
ResetEvent (writer_opening);
|
2020-03-16 23:04:28 +01:00
|
|
|
set_pipe_non_blocking (fc.h, true);
|
2019-05-09 16:58:29 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 19:29:50 +01:00
|
|
|
static DWORD WINAPI
|
|
|
|
fifo_reader_thread (LPVOID param)
|
|
|
|
{
|
|
|
|
fhandler_fifo *fh = (fhandler_fifo *) param;
|
|
|
|
return fh->fifo_reader_thread_func ();
|
|
|
|
}
|
|
|
|
|
2019-03-22 20:30:37 +01:00
|
|
|
DWORD
|
2020-03-26 19:29:50 +01:00
|
|
|
fhandler_fifo::fifo_reader_thread_func ()
|
2019-03-22 20:30:37 +01:00
|
|
|
{
|
2020-04-30 00:53:05 +02:00
|
|
|
HANDLE conn_evt;
|
2019-06-20 21:14:47 +02:00
|
|
|
|
2020-04-30 00:53:05 +02:00
|
|
|
if (!(conn_evt = CreateEvent (NULL, false, false, NULL)))
|
|
|
|
api_fatal ("Can't create connection event, %E");
|
2019-04-14 21:16:01 +02:00
|
|
|
|
2019-03-22 20:30:37 +01:00
|
|
|
while (1)
|
|
|
|
{
|
2020-05-07 00:39:26 +02:00
|
|
|
/* Cleanup the fc_handler list. */
|
2019-03-22 20:30:38 +01:00
|
|
|
fifo_client_lock ();
|
2019-04-14 21:16:04 +02:00
|
|
|
int i = 0;
|
|
|
|
while (i < nhandlers)
|
|
|
|
{
|
2020-05-07 00:39:26 +02:00
|
|
|
if (fc_handler[i].state < fc_connected)
|
2020-03-16 23:04:28 +01:00
|
|
|
delete_client_handler (i);
|
2019-04-14 21:16:04 +02:00
|
|
|
else
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a new client handler. */
|
|
|
|
if (add_client_handler () < 0)
|
2020-04-30 00:53:05 +02:00
|
|
|
api_fatal ("Can't add a client handler, %E");
|
2019-03-22 20:30:38 +01:00
|
|
|
|
2019-04-14 21:16:04 +02:00
|
|
|
/* Listen for a writer to connect to the new client handler. */
|
|
|
|
fifo_client_handler& fc = fc_handler[nhandlers - 1];
|
2020-03-26 19:29:50 +01:00
|
|
|
fifo_client_unlock ();
|
2019-05-09 17:55:30 +02:00
|
|
|
NTSTATUS status;
|
|
|
|
IO_STATUS_BLOCK io;
|
2020-04-30 00:53:05 +02:00
|
|
|
bool cancel = false;
|
2019-04-14 21:16:04 +02:00
|
|
|
|
2020-04-30 00:53:05 +02:00
|
|
|
status = NtFsControlFile (fc.h, conn_evt, NULL, NULL, &io,
|
2019-06-20 21:14:47 +02:00
|
|
|
FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
|
2019-05-09 17:55:30 +02:00
|
|
|
if (status == STATUS_PENDING)
|
|
|
|
{
|
2020-03-26 19:29:50 +01:00
|
|
|
HANDLE w[2] = { conn_evt, cancel_evt };
|
|
|
|
switch (WaitForMultipleObjects (2, w, false, INFINITE))
|
2019-04-14 21:16:04 +02:00
|
|
|
{
|
2019-05-09 17:55:30 +02:00
|
|
|
case WAIT_OBJECT_0:
|
|
|
|
status = io.Status;
|
2019-04-14 21:16:04 +02:00
|
|
|
break;
|
2019-05-09 17:55:30 +02:00
|
|
|
case WAIT_OBJECT_0 + 1:
|
|
|
|
status = STATUS_THREAD_IS_TERMINATING;
|
2020-04-30 00:53:05 +02:00
|
|
|
cancel = true;
|
2019-04-14 21:16:04 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-30 00:53:05 +02:00
|
|
|
api_fatal ("WFMO failed, %E");
|
2019-04-14 21:16:04 +02:00
|
|
|
}
|
2019-05-09 17:55:30 +02:00
|
|
|
}
|
|
|
|
HANDLE ph = NULL;
|
2020-04-30 00:53:05 +02:00
|
|
|
NTSTATUS status1;
|
|
|
|
|
2019-06-22 16:07:48 +02:00
|
|
|
fifo_client_lock ();
|
2019-05-09 17:55:30 +02:00
|
|
|
switch (status)
|
|
|
|
{
|
|
|
|
case STATUS_SUCCESS:
|
|
|
|
case STATUS_PIPE_CONNECTED:
|
|
|
|
record_connection (fc);
|
|
|
|
break;
|
2020-05-07 00:39:26 +02:00
|
|
|
case STATUS_PIPE_CLOSING:
|
|
|
|
record_connection (fc, fc_closing);
|
|
|
|
break;
|
2019-05-09 17:55:30 +02:00
|
|
|
case STATUS_THREAD_IS_TERMINATING:
|
2020-04-30 00:53:05 +02:00
|
|
|
/* Try to connect a bogus client. Otherwise fc is still
|
|
|
|
listening, and the next connection might not get recorded. */
|
|
|
|
status1 = open_pipe (ph);
|
|
|
|
WaitForSingleObject (conn_evt, INFINITE);
|
|
|
|
if (NT_SUCCESS (status1))
|
|
|
|
/* Bogus cilent connected. */
|
|
|
|
delete_client_handler (nhandlers - 1);
|
2019-05-09 17:55:30 +02:00
|
|
|
else
|
2020-04-30 00:53:05 +02:00
|
|
|
/* Did a real client connect? */
|
|
|
|
switch (io.Status)
|
|
|
|
{
|
|
|
|
case STATUS_SUCCESS:
|
|
|
|
case STATUS_PIPE_CONNECTED:
|
|
|
|
record_connection (fc);
|
|
|
|
break;
|
|
|
|
case STATUS_PIPE_CLOSING:
|
|
|
|
record_connection (fc, fc_closing);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debug_printf ("NtFsControlFile status %y after failing to connect bogus client or real client", io.Status);
|
|
|
|
fc.state = fc_unknown;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2019-05-09 17:55:30 +02:00
|
|
|
default:
|
2020-04-30 00:53:05 +02:00
|
|
|
break;
|
2019-05-09 17:55:30 +02:00
|
|
|
}
|
2019-06-22 16:07:48 +02:00
|
|
|
fifo_client_unlock ();
|
2020-04-30 00:53:05 +02:00
|
|
|
if (ph)
|
|
|
|
NtClose (ph);
|
|
|
|
if (cancel)
|
2020-03-26 19:29:50 +01:00
|
|
|
goto canceled;
|
2019-03-22 20:30:37 +01:00
|
|
|
}
|
2020-03-26 19:29:50 +01:00
|
|
|
canceled:
|
2020-04-30 00:53:05 +02:00
|
|
|
if (conn_evt)
|
|
|
|
NtClose (conn_evt);
|
2020-03-26 19:29:50 +01:00
|
|
|
/* automatically return the cygthread to the cygthread pool */
|
|
|
|
_my_tls._ctinfo->auto_release ();
|
2020-04-30 00:53:05 +02:00
|
|
|
return 0;
|
2019-03-22 20:30:37 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 17:29:56 +01:00
|
|
|
int
|
|
|
|
fhandler_fifo::create_shmem ()
|
|
|
|
{
|
|
|
|
HANDLE sect;
|
|
|
|
OBJECT_ATTRIBUTES attr;
|
|
|
|
NTSTATUS status;
|
|
|
|
LARGE_INTEGER size = { .QuadPart = sizeof (fifo_shmem_t) };
|
|
|
|
SIZE_T viewsize = sizeof (fifo_shmem_t);
|
|
|
|
PVOID addr = NULL;
|
|
|
|
UNICODE_STRING uname;
|
|
|
|
WCHAR shmem_name[MAX_PATH];
|
|
|
|
|
|
|
|
__small_swprintf (shmem_name, L"fifo-shmem.%08x.%016X", get_dev (),
|
|
|
|
get_ino ());
|
|
|
|
RtlInitUnicodeString (&uname, shmem_name);
|
|
|
|
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT,
|
|
|
|
get_shared_parent_dir (), NULL);
|
|
|
|
status = NtCreateSection (§, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
|
|
|
|
| SECTION_MAP_READ | SECTION_MAP_WRITE,
|
|
|
|
&attr, &size, PAGE_READWRITE, SEC_COMMIT, NULL);
|
|
|
|
if (status == STATUS_OBJECT_NAME_COLLISION)
|
|
|
|
status = NtOpenSection (§, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
|
|
|
|
| SECTION_MAP_READ | SECTION_MAP_WRITE, &attr);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
{
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
status = NtMapViewOfSection (sect, NtCurrentProcess (), &addr, 0, viewsize,
|
|
|
|
NULL, &viewsize, ViewShare, 0, PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
{
|
|
|
|
NtClose (sect);
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
shmem_handle = sect;
|
|
|
|
shmem = (fifo_shmem_t *) addr;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* shmem_handle must be valid when this is called. */
|
|
|
|
int
|
|
|
|
fhandler_fifo::reopen_shmem ()
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
SIZE_T viewsize = sizeof (fifo_shmem_t);
|
|
|
|
PVOID addr = NULL;
|
|
|
|
|
|
|
|
status = NtMapViewOfSection (shmem_handle, NtCurrentProcess (), &addr,
|
|
|
|
0, viewsize, NULL, &viewsize, ViewShare,
|
|
|
|
0, PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
{
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
shmem = (fifo_shmem_t *) addr;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-09-20 02:31:13 +02:00
|
|
|
int
|
2007-07-07 19:00:33 +02:00
|
|
|
fhandler_fifo::open (int flags, mode_t)
|
2003-09-20 02:31:13 +02:00
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
int saved_errno = 0;
|
2007-07-07 19:00:33 +02:00
|
|
|
|
2019-06-27 13:46:14 +02:00
|
|
|
if (flags & O_PATH)
|
2020-01-23 17:31:04 +01:00
|
|
|
return open_fs (flags);
|
2019-06-27 13:46:14 +02:00
|
|
|
|
2011-10-30 05:50:36 +01:00
|
|
|
/* Determine what we're doing with this fhandler: reading, writing, both */
|
|
|
|
switch (flags & O_ACCMODE)
|
2003-09-20 02:31:13 +02:00
|
|
|
{
|
2011-10-30 05:50:36 +01:00
|
|
|
case O_RDONLY:
|
2020-01-23 17:31:04 +01:00
|
|
|
reader = true;
|
2011-10-30 05:50:36 +01:00
|
|
|
break;
|
|
|
|
case O_WRONLY:
|
|
|
|
writer = true;
|
|
|
|
break;
|
|
|
|
case O_RDWR:
|
2012-01-22 22:43:25 +01:00
|
|
|
reader = true;
|
2019-04-14 21:15:57 +02:00
|
|
|
duplexer = true;
|
2011-10-30 05:50:36 +01:00
|
|
|
break;
|
|
|
|
default:
|
2007-07-07 19:00:33 +02:00
|
|
|
set_errno (EINVAL);
|
2020-03-17 19:14:47 +01:00
|
|
|
goto err;
|
2007-07-07 19:00:33 +02:00
|
|
|
}
|
2009-07-24 22:54:33 +02:00
|
|
|
|
2012-01-22 22:43:25 +01:00
|
|
|
debug_only_printf ("reader %d, writer %d, duplexer %d", reader, writer, duplexer);
|
2011-10-30 05:50:36 +01:00
|
|
|
set_flags (flags);
|
2019-03-26 00:06:10 +01:00
|
|
|
if (reader && !duplexer)
|
2019-03-22 20:30:37 +01:00
|
|
|
nohandle (true);
|
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
/* Create control events for this named pipe */
|
2011-10-30 05:50:36 +01:00
|
|
|
char char_sa_buf[1024];
|
|
|
|
LPSECURITY_ATTRIBUTES sa_buf;
|
|
|
|
sa_buf = sec_user_cloexec (flags & O_CLOEXEC, (PSECURITY_ATTRIBUTES) char_sa_buf,
|
|
|
|
cygheap->user.sid());
|
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
char npbuf[MAX_PATH];
|
|
|
|
__small_sprintf (npbuf, "r-event.%08x.%016X", get_dev (), get_ino ());
|
2020-03-17 19:14:47 +01:00
|
|
|
if (!(read_ready = CreateEvent (sa_buf, true, false, npbuf)))
|
2011-10-30 05:50:36 +01:00
|
|
|
{
|
2019-03-22 20:30:36 +01:00
|
|
|
debug_printf ("CreateEvent for %s failed, %E", npbuf);
|
2020-03-17 19:14:47 +01:00
|
|
|
__seterrno ();
|
|
|
|
goto err;
|
2011-10-30 05:50:36 +01:00
|
|
|
}
|
2019-03-22 20:30:36 +01:00
|
|
|
npbuf[0] = 'w';
|
2019-06-19 17:14:37 +02:00
|
|
|
if (!(write_ready = CreateEvent (sa_buf, true, false, npbuf)))
|
2007-07-07 19:00:33 +02:00
|
|
|
{
|
2019-03-22 20:30:36 +01:00
|
|
|
debug_printf ("CreateEvent for %s failed, %E", npbuf);
|
2020-03-17 19:14:47 +01:00
|
|
|
__seterrno ();
|
|
|
|
goto err_close_read_ready;
|
2011-10-30 05:50:36 +01:00
|
|
|
}
|
2020-04-26 15:38:46 +02:00
|
|
|
npbuf[0] = 'o';
|
|
|
|
if (!(writer_opening = CreateEvent (sa_buf, true, false, npbuf)))
|
|
|
|
{
|
|
|
|
debug_printf ("CreateEvent for %s failed, %E", npbuf);
|
2020-03-17 19:14:47 +01:00
|
|
|
__seterrno ();
|
|
|
|
goto err_close_write_ready;
|
2019-03-26 00:06:10 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 17:29:56 +01:00
|
|
|
/* If we're reading, signal read_ready, create the shared memory,
|
|
|
|
and start the fifo_reader_thread. */
|
2019-03-22 20:30:36 +01:00
|
|
|
if (reader)
|
2011-10-30 05:50:36 +01:00
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
SetEvent (read_ready);
|
2020-03-17 17:29:56 +01:00
|
|
|
if (create_shmem () < 0)
|
2020-03-26 19:29:50 +01:00
|
|
|
goto err_close_writer_opening;
|
2020-03-27 14:43:30 +01:00
|
|
|
inc_nreaders ();
|
2020-03-17 17:29:56 +01:00
|
|
|
if (!(cancel_evt = create_event ()))
|
2020-03-27 14:43:30 +01:00
|
|
|
goto err_dec_nreaders;
|
2020-03-26 19:29:50 +01:00
|
|
|
if (!(thr_sync_evt = create_event ()))
|
|
|
|
goto err_close_cancel_evt;
|
2020-03-26 00:22:10 +01:00
|
|
|
me.winpid = GetCurrentProcessId ();
|
|
|
|
me.fh = this;
|
2020-03-26 19:29:50 +01:00
|
|
|
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
|
2020-03-17 19:14:47 +01:00
|
|
|
|
|
|
|
/* If we're a duplexer, we need a handle for writing. */
|
|
|
|
if (duplexer)
|
2019-04-20 17:41:12 +02:00
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
HANDLE ph = NULL;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
status = open_pipe (ph);
|
|
|
|
if (NT_SUCCESS (status))
|
|
|
|
{
|
|
|
|
set_handle (ph);
|
|
|
|
set_pipe_non_blocking (ph, flags & O_NONBLOCK);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
|
|
{
|
|
|
|
/* The pipe hasn't been created yet. */
|
|
|
|
yield ();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
goto err_close_reader;
|
|
|
|
}
|
|
|
|
}
|
2019-04-20 17:41:12 +02:00
|
|
|
}
|
2020-03-17 19:14:47 +01:00
|
|
|
/* Not a duplexer; wait for a writer to connect. */
|
|
|
|
else if (!wait (write_ready))
|
|
|
|
goto err_close_reader;
|
|
|
|
goto success;
|
2011-10-30 05:50:36 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 19:14:47 +01:00
|
|
|
/* If we're writing, wait for read_ready, connect to the pipe, and
|
|
|
|
signal write_ready. */
|
2011-10-30 05:50:36 +01:00
|
|
|
if (writer)
|
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
NTSTATUS status;
|
|
|
|
|
2020-04-26 15:38:46 +02:00
|
|
|
SetEvent (writer_opening);
|
2020-03-17 19:14:47 +01:00
|
|
|
if (!wait (read_ready))
|
|
|
|
{
|
|
|
|
ResetEvent (writer_opening);
|
|
|
|
goto err_close_writer_opening;
|
|
|
|
}
|
2019-04-14 21:16:02 +02:00
|
|
|
while (1)
|
2019-03-22 20:30:37 +01:00
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
status = open_pipe (get_handle ());
|
2019-04-14 21:16:02 +02:00
|
|
|
if (NT_SUCCESS (status))
|
2020-03-17 19:14:47 +01:00
|
|
|
goto writer_success;
|
|
|
|
else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
2019-04-14 21:16:02 +02:00
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
/* The pipe hasn't been created yet. */
|
|
|
|
yield ();
|
|
|
|
continue;
|
2019-04-14 21:16:02 +02:00
|
|
|
}
|
|
|
|
else if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status))
|
2020-03-17 19:14:47 +01:00
|
|
|
break;
|
2019-04-14 21:16:02 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
debug_printf ("create of writer failed");
|
|
|
|
__seterrno_from_nt_status (status);
|
2020-04-26 15:38:46 +02:00
|
|
|
ResetEvent (writer_opening);
|
2020-03-17 19:14:47 +01:00
|
|
|
goto err_close_writer_opening;
|
2019-04-14 21:16:02 +02:00
|
|
|
}
|
2019-03-22 20:30:37 +01:00
|
|
|
}
|
2020-03-17 19:14:47 +01:00
|
|
|
|
|
|
|
/* We should get here only if the system is heavily loaded
|
|
|
|
and/or many writers are trying to connect simultaneously */
|
|
|
|
while (1)
|
2020-04-26 15:38:46 +02:00
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
SetEvent (writer_opening);
|
|
|
|
if (!wait (read_ready))
|
|
|
|
{
|
|
|
|
ResetEvent (writer_opening);
|
|
|
|
goto err_close_writer_opening;
|
|
|
|
}
|
|
|
|
status = wait_open_pipe (get_handle ());
|
|
|
|
if (NT_SUCCESS (status))
|
|
|
|
goto writer_success;
|
|
|
|
else if (status == STATUS_IO_TIMEOUT)
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug_printf ("create of writer failed");
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
ResetEvent (writer_opening);
|
|
|
|
goto err_close_writer_opening;
|
|
|
|
}
|
2020-04-26 15:38:46 +02:00
|
|
|
}
|
2003-09-20 02:31:13 +02:00
|
|
|
}
|
2020-03-17 19:14:47 +01:00
|
|
|
writer_success:
|
|
|
|
set_pipe_non_blocking (get_handle (), flags & O_NONBLOCK);
|
|
|
|
SetEvent (write_ready);
|
|
|
|
success:
|
|
|
|
return 1;
|
|
|
|
err_close_reader:
|
|
|
|
saved_errno = get_errno ();
|
|
|
|
close ();
|
|
|
|
set_errno (saved_errno);
|
|
|
|
return 0;
|
2020-03-26 19:29:50 +01:00
|
|
|
err_close_cancel_evt:
|
|
|
|
NtClose (cancel_evt);
|
2020-03-27 14:43:30 +01:00
|
|
|
err_dec_nreaders:
|
|
|
|
if (dec_nreaders () == 0)
|
|
|
|
ResetEvent (read_ready);
|
|
|
|
/* err_close_shmem: */
|
2020-03-17 17:29:56 +01:00
|
|
|
NtUnmapViewOfSection (NtCurrentProcess (), shmem);
|
|
|
|
NtClose (shmem_handle);
|
2020-03-17 19:14:47 +01:00
|
|
|
err_close_writer_opening:
|
|
|
|
NtClose (writer_opening);
|
|
|
|
err_close_write_ready:
|
|
|
|
NtClose (write_ready);
|
|
|
|
err_close_read_ready:
|
|
|
|
NtClose (read_ready);
|
|
|
|
err:
|
|
|
|
if (get_handle ())
|
|
|
|
NtClose (get_handle ());
|
|
|
|
return 0;
|
2003-09-20 02:31:13 +02:00
|
|
|
}
|
|
|
|
|
2018-10-10 13:20:04 +02:00
|
|
|
off_t
|
|
|
|
fhandler_fifo::lseek (off_t offset, int whence)
|
|
|
|
{
|
|
|
|
debug_printf ("(%D, %d)", offset, whence);
|
|
|
|
set_errno (ESPIPE);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-07-07 19:00:33 +02:00
|
|
|
bool
|
2011-10-30 05:50:36 +01:00
|
|
|
fhandler_fifo::wait (HANDLE h)
|
2003-09-20 02:31:13 +02:00
|
|
|
{
|
2011-10-30 05:50:36 +01:00
|
|
|
#ifdef DEBUGGING
|
|
|
|
const char *what;
|
|
|
|
if (h == read_ready)
|
|
|
|
what = "reader";
|
|
|
|
else
|
2019-03-22 20:30:36 +01:00
|
|
|
what = "writer";
|
2011-10-30 05:50:36 +01:00
|
|
|
#endif
|
|
|
|
/* Set the wait to zero for non-blocking I/O-related events. */
|
|
|
|
DWORD wait = ((h == read_ready || h == write_ready)
|
|
|
|
&& get_flags () & O_NONBLOCK) ? 0 : INFINITE;
|
|
|
|
|
|
|
|
debug_only_printf ("waiting for %s", what);
|
|
|
|
/* Wait for the event. Set errno, as appropriate if something goes wrong. */
|
2011-12-09 17:02:56 +01:00
|
|
|
switch (cygwait (h, wait))
|
2006-06-23 02:19:39 +02:00
|
|
|
{
|
2011-10-30 05:50:36 +01:00
|
|
|
case WAIT_OBJECT_0:
|
|
|
|
debug_only_printf ("successfully waited for %s", what);
|
|
|
|
return true;
|
2012-06-17 22:50:24 +02:00
|
|
|
case WAIT_SIGNALED:
|
|
|
|
debug_only_printf ("interrupted by signal while waiting for %s", what);
|
|
|
|
set_errno (EINTR);
|
|
|
|
return false;
|
|
|
|
case WAIT_CANCELED:
|
|
|
|
debug_only_printf ("cancellable interruption while waiting for %s", what);
|
|
|
|
pthread::static_cancel_self (); /* never returns */
|
|
|
|
break;
|
2011-10-30 05:50:36 +01:00
|
|
|
case WAIT_TIMEOUT:
|
|
|
|
if (h == write_ready)
|
2009-07-24 22:54:33 +02:00
|
|
|
{
|
2011-10-30 05:50:36 +01:00
|
|
|
debug_only_printf ("wait timed out waiting for write but will still open reader since non-blocking mode");
|
|
|
|
return true;
|
2009-07-24 22:54:33 +02:00
|
|
|
}
|
2011-10-30 05:50:36 +01:00
|
|
|
else
|
2009-07-24 22:54:33 +02:00
|
|
|
{
|
2011-10-30 05:50:36 +01:00
|
|
|
set_errno (ENXIO);
|
2009-07-24 22:54:33 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
2011-10-30 05:50:36 +01:00
|
|
|
default:
|
|
|
|
debug_only_printf ("unknown error while waiting for %s", what);
|
|
|
|
__seterrno ();
|
|
|
|
return false;
|
|
|
|
}
|
2007-07-07 19:00:33 +02:00
|
|
|
}
|
2006-06-23 02:19:39 +02:00
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
ssize_t __reg3
|
|
|
|
fhandler_fifo::raw_write (const void *ptr, size_t len)
|
|
|
|
{
|
|
|
|
ssize_t ret = -1;
|
2019-06-08 17:05:39 +02:00
|
|
|
size_t nbytes = 0;
|
|
|
|
ULONG chunk;
|
2019-04-15 17:43:57 +02:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2019-03-22 20:30:36 +01:00
|
|
|
IO_STATUS_BLOCK io;
|
2019-04-15 17:43:57 +02:00
|
|
|
HANDLE evt = NULL;
|
2019-03-22 20:30:36 +01:00
|
|
|
|
2019-06-08 17:05:39 +02:00
|
|
|
if (!len)
|
|
|
|
return 0;
|
|
|
|
|
2019-04-15 17:43:57 +02:00
|
|
|
if (len <= max_atomic_write)
|
|
|
|
chunk = len;
|
|
|
|
else if (is_nonblocking ())
|
|
|
|
chunk = len = max_atomic_write;
|
|
|
|
else
|
|
|
|
chunk = max_atomic_write;
|
|
|
|
|
|
|
|
/* Create a wait event if the FIFO is in blocking mode. */
|
|
|
|
if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL)))
|
2019-06-08 17:05:39 +02:00
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
return -1;
|
|
|
|
}
|
2019-04-15 17:43:57 +02:00
|
|
|
|
|
|
|
/* Write in chunks, accumulating a total. If there's an error, just
|
|
|
|
return the accumulated total unless the first write fails, in
|
|
|
|
which case return -1. */
|
|
|
|
while (nbytes < len)
|
2019-03-22 20:30:36 +01:00
|
|
|
{
|
2019-04-15 17:43:57 +02:00
|
|
|
ULONG_PTR nbytes_now = 0;
|
|
|
|
size_t left = len - nbytes;
|
2019-06-08 17:05:39 +02:00
|
|
|
ULONG len1;
|
|
|
|
DWORD waitret = WAIT_OBJECT_0;
|
|
|
|
|
2019-04-15 17:43:57 +02:00
|
|
|
if (left > chunk)
|
|
|
|
len1 = chunk;
|
2019-03-22 20:30:36 +01:00
|
|
|
else
|
2019-06-08 17:05:39 +02:00
|
|
|
len1 = (ULONG) left;
|
2019-04-15 17:43:57 +02:00
|
|
|
nbytes_now = 0;
|
|
|
|
status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
|
|
|
|
(PVOID) ptr, len1, NULL, NULL);
|
|
|
|
if (evt && status == STATUS_PENDING)
|
|
|
|
{
|
2019-06-08 17:05:39 +02:00
|
|
|
waitret = cygwait (evt);
|
|
|
|
if (waitret == WAIT_OBJECT_0)
|
|
|
|
status = io.Status;
|
2019-04-15 17:43:57 +02:00
|
|
|
}
|
2019-06-08 17:05:39 +02:00
|
|
|
if (waitret == WAIT_CANCELED)
|
|
|
|
status = STATUS_THREAD_CANCELED;
|
|
|
|
else if (waitret == WAIT_SIGNALED)
|
|
|
|
status = STATUS_THREAD_SIGNALED;
|
|
|
|
else if (isclosed ()) /* A signal handler might have closed the fd. */
|
|
|
|
{
|
|
|
|
if (waitret == WAIT_OBJECT_0)
|
|
|
|
set_errno (EBADF);
|
|
|
|
else
|
|
|
|
__seterrno ();
|
|
|
|
}
|
|
|
|
else if (NT_SUCCESS (status))
|
2019-04-15 17:43:57 +02:00
|
|
|
{
|
|
|
|
nbytes_now = io.Information;
|
|
|
|
/* NtWriteFile returns success with # of bytes written == 0
|
|
|
|
if writing on a non-blocking pipe fails because the pipe
|
|
|
|
buffer doesn't have sufficient space. */
|
|
|
|
if (nbytes_now == 0)
|
|
|
|
set_errno (EAGAIN);
|
|
|
|
ptr = ((char *) ptr) + chunk;
|
|
|
|
nbytes += nbytes_now;
|
|
|
|
}
|
|
|
|
else if (STATUS_PIPE_IS_CLOSED (status))
|
|
|
|
{
|
|
|
|
set_errno (EPIPE);
|
|
|
|
raise (SIGPIPE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
if (nbytes_now == 0)
|
|
|
|
len = 0; /* Terminate loop. */
|
|
|
|
if (nbytes > 0)
|
|
|
|
ret = nbytes;
|
2019-03-22 20:30:36 +01:00
|
|
|
}
|
2019-04-15 17:43:57 +02:00
|
|
|
if (evt)
|
2020-03-17 15:36:34 +01:00
|
|
|
NtClose (evt);
|
2019-06-08 17:05:39 +02:00
|
|
|
if (status == STATUS_THREAD_SIGNALED && ret < 0)
|
2019-04-15 17:43:57 +02:00
|
|
|
set_errno (EINTR);
|
|
|
|
else if (status == STATUS_THREAD_CANCELED)
|
|
|
|
pthread::static_cancel_self ();
|
2019-03-22 20:30:36 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-04-26 15:38:46 +02:00
|
|
|
/* A reader is at EOF if the pipe is empty and no writers are open.
|
|
|
|
hit_eof is called by raw_read and select.cc:peek_fifo if it appears
|
|
|
|
that we are at EOF after polling the fc_handlers. We recheck this
|
|
|
|
in case a writer opened while we were polling. */
|
2019-03-22 20:30:38 +01:00
|
|
|
bool
|
|
|
|
fhandler_fifo::hit_eof ()
|
|
|
|
{
|
2020-04-26 15:38:46 +02:00
|
|
|
bool ret = maybe_eof () && !IsEventSignalled (writer_opening);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
yield ();
|
|
|
|
/* Wait for the reader thread to finish recording any connection. */
|
2019-04-14 21:15:56 +02:00
|
|
|
fifo_client_lock ();
|
|
|
|
fifo_client_unlock ();
|
2020-04-26 15:38:46 +02:00
|
|
|
ret = maybe_eof ();
|
|
|
|
}
|
|
|
|
return ret;
|
2019-03-22 20:30:38 +01:00
|
|
|
}
|
|
|
|
|
2013-05-01 03:20:37 +02:00
|
|
|
void __reg3
|
2009-03-27 16:04:42 +01:00
|
|
|
fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
2007-07-07 19:00:33 +02:00
|
|
|
{
|
2019-06-08 17:05:39 +02:00
|
|
|
if (!len)
|
|
|
|
return;
|
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
while (1)
|
2011-10-30 05:50:36 +01:00
|
|
|
{
|
2019-03-22 20:30:37 +01:00
|
|
|
/* Poll the connected clients for input. */
|
2020-04-26 15:38:46 +02:00
|
|
|
int nconnected = 0;
|
2019-03-22 20:30:38 +01:00
|
|
|
fifo_client_lock ();
|
2019-04-14 21:15:56 +02:00
|
|
|
for (int i = 0; i < nhandlers; i++)
|
2020-05-07 00:39:26 +02:00
|
|
|
if (fc_handler[i].state >= fc_connected)
|
2019-03-22 20:30:37 +01:00
|
|
|
{
|
2019-06-21 23:33:30 +02:00
|
|
|
NTSTATUS status;
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
size_t nbytes = 0;
|
|
|
|
|
2020-04-26 15:38:46 +02:00
|
|
|
nconnected++;
|
|
|
|
status = NtReadFile (fc_handler[i].h, NULL, NULL, NULL,
|
2019-06-21 23:33:30 +02:00
|
|
|
&io, in_ptr, len, NULL, NULL);
|
|
|
|
switch (status)
|
2019-03-22 20:30:37 +01:00
|
|
|
{
|
2019-06-21 23:33:30 +02:00
|
|
|
case STATUS_SUCCESS:
|
|
|
|
case STATUS_BUFFER_OVERFLOW:
|
|
|
|
/* io.Information is supposedly valid. */
|
|
|
|
nbytes = io.Information;
|
|
|
|
if (nbytes > 0)
|
|
|
|
{
|
|
|
|
len = nbytes;
|
|
|
|
fifo_client_unlock ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATUS_PIPE_EMPTY:
|
|
|
|
break;
|
|
|
|
case STATUS_PIPE_BROKEN:
|
2020-05-07 00:39:26 +02:00
|
|
|
fc_handler[i].state = fc_disconnected;
|
2019-06-21 23:33:30 +02:00
|
|
|
nconnected--;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debug_printf ("NtReadFile status %y", status);
|
2020-05-07 00:39:26 +02:00
|
|
|
fc_handler[i].state = fc_error;
|
2019-03-22 20:30:37 +01:00
|
|
|
nconnected--;
|
2020-05-07 00:39:26 +02:00
|
|
|
break;
|
2019-03-22 20:30:37 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-26 15:38:46 +02:00
|
|
|
maybe_eof (!nconnected && !IsEventSignalled (writer_opening));
|
2019-03-22 20:30:38 +01:00
|
|
|
fifo_client_unlock ();
|
2020-04-26 15:38:46 +02:00
|
|
|
if (maybe_eof () && hit_eof ())
|
|
|
|
{
|
|
|
|
len = 0;
|
|
|
|
return;
|
|
|
|
}
|
2019-03-22 20:30:36 +01:00
|
|
|
if (is_nonblocking ())
|
2011-10-30 05:50:36 +01:00
|
|
|
{
|
2019-03-22 20:30:36 +01:00
|
|
|
set_errno (EAGAIN);
|
|
|
|
goto errout;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-06-08 17:05:39 +02:00
|
|
|
/* Allow interruption. */
|
|
|
|
DWORD waitret = cygwait (NULL, cw_nowait, cw_cancel | cw_sig_eintr);
|
|
|
|
if (waitret == WAIT_CANCELED)
|
|
|
|
pthread::static_cancel_self ();
|
|
|
|
else if (waitret == WAIT_SIGNALED)
|
2019-03-22 20:30:36 +01:00
|
|
|
{
|
2019-06-08 17:05:39 +02:00
|
|
|
if (_my_tls.call_signal_handler ())
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
set_errno (EINTR);
|
|
|
|
goto errout;
|
|
|
|
}
|
2019-03-22 20:30:36 +01:00
|
|
|
}
|
2011-10-30 05:50:36 +01:00
|
|
|
}
|
2019-06-08 17:05:39 +02:00
|
|
|
/* We might have been closed by a signal handler or another thread. */
|
|
|
|
if (isclosed ())
|
|
|
|
{
|
|
|
|
set_errno (EBADF);
|
|
|
|
goto errout;
|
|
|
|
}
|
|
|
|
/* Don't hog the CPU. */
|
|
|
|
Sleep (1);
|
2011-10-30 05:50:36 +01:00
|
|
|
}
|
|
|
|
errout:
|
2019-06-08 17:05:39 +02:00
|
|
|
len = (size_t) -1;
|
2003-09-20 02:31:13 +02:00
|
|
|
}
|
2007-02-27 13:58:56 +01:00
|
|
|
|
2013-01-21 05:34:52 +01:00
|
|
|
int __reg2
|
2007-02-27 13:58:56 +01:00
|
|
|
fhandler_fifo::fstatvfs (struct statvfs *sfs)
|
|
|
|
{
|
2020-01-24 21:09:03 +01:00
|
|
|
if (get_flags () & O_PATH)
|
|
|
|
/* We already have a handle. */
|
|
|
|
{
|
|
|
|
HANDLE h = get_handle ();
|
|
|
|
if (h)
|
|
|
|
return fstatvfs_by_handle (h, sfs);
|
|
|
|
}
|
|
|
|
|
2007-12-04 14:29:44 +01:00
|
|
|
fhandler_disk_file fh (pc);
|
|
|
|
fh.get_device () = FH_FS;
|
|
|
|
return fh.fstatvfs (sfs);
|
2007-02-27 13:58:56 +01:00
|
|
|
}
|
2009-07-24 22:54:33 +02:00
|
|
|
|
2019-06-22 00:49:11 +02:00
|
|
|
int
|
|
|
|
fifo_client_handler::pipe_state ()
|
|
|
|
{
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
FILE_PIPE_LOCAL_INFORMATION fpli;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
2020-03-16 23:04:28 +01:00
|
|
|
status = NtQueryInformationFile (h, &io, &fpli,
|
2019-06-22 00:49:11 +02:00
|
|
|
sizeof (fpli), FilePipeLocalInformation);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
|
|
{
|
|
|
|
debug_printf ("NtQueryInformationFile status %y", status);
|
|
|
|
__seterrno_from_nt_status (status);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (fpli.ReadDataAvailable > 0)
|
|
|
|
return FILE_PIPE_INPUT_AVAILABLE_STATE;
|
|
|
|
else
|
|
|
|
return fpli.NamedPipeState;
|
|
|
|
}
|
|
|
|
|
2020-04-30 00:53:05 +02:00
|
|
|
void
|
2020-03-26 19:29:50 +01:00
|
|
|
fhandler_fifo::cancel_reader_thread ()
|
2009-07-24 22:54:33 +02:00
|
|
|
{
|
2020-03-26 19:29:50 +01:00
|
|
|
if (cancel_evt)
|
|
|
|
SetEvent (cancel_evt);
|
|
|
|
if (thr_sync_evt)
|
|
|
|
WaitForSingleObject (thr_sync_evt, INFINITE);
|
2019-04-14 21:16:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_fifo::close ()
|
|
|
|
{
|
2020-03-17 19:14:47 +01:00
|
|
|
if (reader)
|
2020-03-26 19:29:50 +01:00
|
|
|
{
|
2020-03-27 14:43:30 +01:00
|
|
|
if (dec_nreaders () == 0)
|
|
|
|
ResetEvent (read_ready);
|
2020-03-26 19:29:50 +01:00
|
|
|
cancel_reader_thread ();
|
|
|
|
if (cancel_evt)
|
|
|
|
NtClose (cancel_evt);
|
|
|
|
if (thr_sync_evt)
|
|
|
|
NtClose (thr_sync_evt);
|
2020-03-17 17:29:56 +01:00
|
|
|
if (shmem)
|
|
|
|
NtUnmapViewOfSection (NtCurrentProcess (), shmem);
|
|
|
|
if (shmem_handle)
|
|
|
|
NtClose (shmem_handle);
|
2020-03-26 19:29:50 +01:00
|
|
|
}
|
2019-03-22 20:30:37 +01:00
|
|
|
if (read_ready)
|
2020-03-17 15:36:34 +01:00
|
|
|
NtClose (read_ready);
|
2019-03-22 20:30:37 +01:00
|
|
|
if (write_ready)
|
2020-03-17 15:36:34 +01:00
|
|
|
NtClose (write_ready);
|
2020-04-26 15:38:46 +02:00
|
|
|
if (writer_opening)
|
|
|
|
NtClose (writer_opening);
|
2019-06-22 16:07:48 +02:00
|
|
|
fifo_client_lock ();
|
2019-04-14 21:15:56 +02:00
|
|
|
for (int i = 0; i < nhandlers; i++)
|
2020-03-16 23:04:28 +01:00
|
|
|
fc_handler[i].close ();
|
2019-06-22 16:07:48 +02:00
|
|
|
fifo_client_unlock ();
|
2020-04-30 00:53:05 +02:00
|
|
|
return fhandler_base::close ();
|
2009-07-24 22:54:33 +02:00
|
|
|
}
|
|
|
|
|
2019-05-09 17:23:44 +02:00
|
|
|
/* If we have a write handle (i.e., we're a duplexer or a writer),
|
|
|
|
keep the nonblocking state of the windows pipe in sync with our
|
|
|
|
nonblocking state. */
|
2019-04-26 00:21:11 +02:00
|
|
|
int
|
|
|
|
fhandler_fifo::fcntl (int cmd, intptr_t arg)
|
|
|
|
{
|
2020-01-23 17:31:05 +01:00
|
|
|
if (cmd != F_SETFL || nohandle () || (get_flags () & O_PATH))
|
2019-04-26 00:21:11 +02:00
|
|
|
return fhandler_base::fcntl (cmd, arg);
|
|
|
|
|
|
|
|
const bool was_nonblocking = is_nonblocking ();
|
|
|
|
int res = fhandler_base::fcntl (cmd, arg);
|
|
|
|
const bool now_nonblocking = is_nonblocking ();
|
|
|
|
if (now_nonblocking != was_nonblocking)
|
|
|
|
set_pipe_non_blocking (get_handle (), now_nonblocking);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2009-07-24 22:54:33 +02:00
|
|
|
int
|
2011-10-16 00:37:30 +02:00
|
|
|
fhandler_fifo::dup (fhandler_base *child, int flags)
|
2009-07-24 22:54:33 +02:00
|
|
|
{
|
2020-03-25 14:31:29 +01:00
|
|
|
int i = 0;
|
2019-04-14 21:16:03 +02:00
|
|
|
fhandler_fifo *fhf = NULL;
|
|
|
|
|
2020-01-23 17:31:05 +01:00
|
|
|
if (get_flags () & O_PATH)
|
|
|
|
return fhandler_base::dup (child, flags);
|
|
|
|
|
2019-03-22 20:30:36 +01:00
|
|
|
if (fhandler_base::dup (child, flags))
|
2020-03-25 14:31:29 +01:00
|
|
|
goto err;
|
2019-04-14 21:16:03 +02:00
|
|
|
|
|
|
|
fhf = (fhandler_fifo *) child;
|
2011-10-30 05:50:36 +01:00
|
|
|
if (!DuplicateHandle (GetCurrentProcess (), read_ready,
|
|
|
|
GetCurrentProcess (), &fhf->read_ready,
|
2020-03-25 14:31:29 +01:00
|
|
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
2011-10-30 05:50:36 +01:00
|
|
|
{
|
|
|
|
__seterrno ();
|
2020-03-25 14:31:29 +01:00
|
|
|
goto err;
|
2011-10-30 05:50:36 +01:00
|
|
|
}
|
|
|
|
if (!DuplicateHandle (GetCurrentProcess (), write_ready,
|
|
|
|
GetCurrentProcess (), &fhf->write_ready,
|
2020-03-25 14:31:29 +01:00
|
|
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
2011-10-30 05:50:36 +01:00
|
|
|
{
|
|
|
|
__seterrno ();
|
2020-03-25 14:31:29 +01:00
|
|
|
goto err_close_read_ready;
|
2009-07-24 22:54:33 +02:00
|
|
|
}
|
2020-04-26 15:38:46 +02:00
|
|
|
if (!DuplicateHandle (GetCurrentProcess (), writer_opening,
|
|
|
|
GetCurrentProcess (), &fhf->writer_opening,
|
|
|
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
goto err_close_write_ready;
|
|
|
|
}
|
2020-03-25 14:31:29 +01:00
|
|
|
if (reader)
|
2019-03-22 20:30:39 +01:00
|
|
|
{
|
2020-05-04 17:36:20 +02:00
|
|
|
/* Make sure the child starts unlocked. */
|
|
|
|
fhf->fifo_client_unlock ();
|
|
|
|
|
2020-03-17 17:29:56 +01:00
|
|
|
if (!DuplicateHandle (GetCurrentProcess (), shmem_handle,
|
|
|
|
GetCurrentProcess (), &fhf->shmem_handle,
|
|
|
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
goto err_close_writer_opening;
|
|
|
|
}
|
|
|
|
if (fhf->reopen_shmem () < 0)
|
|
|
|
goto err_close_shmem_handle;
|
2020-03-25 14:31:29 +01:00
|
|
|
fifo_client_lock ();
|
|
|
|
for (i = 0; i < nhandlers; i++)
|
|
|
|
{
|
|
|
|
if (!DuplicateHandle (GetCurrentProcess (), fc_handler[i].h,
|
|
|
|
GetCurrentProcess (), &fhf->fc_handler[i].h,
|
|
|
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < nhandlers)
|
2019-03-22 20:30:39 +01:00
|
|
|
{
|
2019-06-22 16:07:48 +02:00
|
|
|
fifo_client_unlock ();
|
2020-03-25 14:31:29 +01:00
|
|
|
goto err_close_handlers;
|
2019-03-22 20:30:39 +01:00
|
|
|
}
|
2020-03-25 14:31:29 +01:00
|
|
|
fifo_client_unlock ();
|
2020-03-26 19:29:50 +01:00
|
|
|
if (!(fhf->cancel_evt = create_event ()))
|
2020-03-25 14:31:29 +01:00
|
|
|
goto err_close_handlers;
|
2020-03-26 19:29:50 +01:00
|
|
|
if (!(fhf->thr_sync_evt = create_event ()))
|
|
|
|
goto err_close_cancel_evt;
|
2020-03-27 14:43:30 +01:00
|
|
|
inc_nreaders ();
|
2020-03-26 00:22:10 +01:00
|
|
|
fhf->me.fh = fhf;
|
2020-03-27 14:43:30 +01:00
|
|
|
new cygthread (fifo_reader_thread, fhf, "fifo_reader", fhf->thr_sync_evt);
|
2019-03-22 20:30:39 +01:00
|
|
|
}
|
2020-03-25 14:31:29 +01:00
|
|
|
return 0;
|
2020-03-26 19:29:50 +01:00
|
|
|
err_close_cancel_evt:
|
|
|
|
NtClose (fhf->cancel_evt);
|
2020-03-25 14:31:29 +01:00
|
|
|
err_close_handlers:
|
|
|
|
for (int j = 0; j < i; j++)
|
|
|
|
fhf->fc_handler[j].close ();
|
2020-03-17 17:29:56 +01:00
|
|
|
NtUnmapViewOfSection (GetCurrentProcess (), fhf->shmem);
|
|
|
|
err_close_shmem_handle:
|
|
|
|
NtClose (fhf->shmem_handle);
|
|
|
|
err_close_writer_opening:
|
2020-04-26 15:38:46 +02:00
|
|
|
NtClose (fhf->writer_opening);
|
|
|
|
err_close_write_ready:
|
2020-03-25 14:31:29 +01:00
|
|
|
NtClose (fhf->write_ready);
|
|
|
|
err_close_read_ready:
|
|
|
|
NtClose (fhf->read_ready);
|
|
|
|
err:
|
|
|
|
return -1;
|
2011-10-30 05:50:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fhandler_fifo::fixup_after_fork (HANDLE parent)
|
|
|
|
{
|
2019-03-22 20:30:36 +01:00
|
|
|
fhandler_base::fixup_after_fork (parent);
|
2011-10-30 05:50:36 +01:00
|
|
|
fork_fixup (parent, read_ready, "read_ready");
|
|
|
|
fork_fixup (parent, write_ready, "write_ready");
|
2020-04-26 15:38:46 +02:00
|
|
|
fork_fixup (parent, writer_opening, "writer_opening");
|
2020-05-04 17:36:20 +02:00
|
|
|
if (reader)
|
|
|
|
{
|
|
|
|
/* Make sure the child starts unlocked. */
|
|
|
|
fifo_client_unlock ();
|
|
|
|
|
2020-03-17 17:29:56 +01:00
|
|
|
fork_fixup (parent, shmem_handle, "shmem_handle");
|
|
|
|
if (reopen_shmem () < 0)
|
|
|
|
api_fatal ("Can't reopen shared memory during fork, %E");
|
2020-05-04 17:36:20 +02:00
|
|
|
fifo_client_lock ();
|
|
|
|
for (int i = 0; i < nhandlers; i++)
|
|
|
|
fork_fixup (parent, fc_handler[i].h, "fc_handler[].h");
|
|
|
|
fifo_client_unlock ();
|
2020-03-26 19:29:50 +01:00
|
|
|
if (!(cancel_evt = create_event ()))
|
|
|
|
api_fatal ("Can't create reader thread cancel event during fork, %E");
|
|
|
|
if (!(thr_sync_evt = create_event ()))
|
|
|
|
api_fatal ("Can't create reader thread sync event during fork, %E");
|
2020-03-27 14:43:30 +01:00
|
|
|
inc_nreaders ();
|
2020-03-26 00:22:10 +01:00
|
|
|
me.winpid = GetCurrentProcessId ();
|
2020-03-26 19:29:50 +01:00
|
|
|
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
|
2020-05-04 17:36:20 +02:00
|
|
|
}
|
2009-07-24 22:54:33 +02:00
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:52 +02:00
|
|
|
void
|
|
|
|
fhandler_fifo::fixup_after_exec ()
|
|
|
|
{
|
|
|
|
fhandler_base::fixup_after_exec ();
|
2020-05-04 17:36:20 +02:00
|
|
|
if (reader && !close_on_exec ())
|
|
|
|
{
|
|
|
|
/* Make sure the child starts unlocked. */
|
|
|
|
fifo_client_unlock ();
|
|
|
|
|
2020-03-17 17:29:56 +01:00
|
|
|
if (reopen_shmem () < 0)
|
|
|
|
api_fatal ("Can't reopen shared memory during exec, %E");
|
2020-03-26 00:22:10 +01:00
|
|
|
me.winpid = GetCurrentProcessId ();
|
2020-03-26 19:29:50 +01:00
|
|
|
if (!(cancel_evt = create_event ()))
|
|
|
|
api_fatal ("Can't create reader thread cancel event during exec, %E");
|
|
|
|
if (!(thr_sync_evt = create_event ()))
|
|
|
|
api_fatal ("Can't create reader thread sync event during exec, %E");
|
2020-03-27 14:43:30 +01:00
|
|
|
/* At this moment we're a new reader. The count will be
|
|
|
|
decremented when the parent closes. */
|
|
|
|
inc_nreaders ();
|
2020-03-26 19:29:50 +01:00
|
|
|
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
|
2020-05-04 17:36:20 +02:00
|
|
|
}
|
2019-04-18 17:39:52 +02:00
|
|
|
}
|
|
|
|
|
2009-07-24 22:54:33 +02:00
|
|
|
void
|
|
|
|
fhandler_fifo::set_close_on_exec (bool val)
|
|
|
|
{
|
|
|
|
fhandler_base::set_close_on_exec (val);
|
2011-10-30 05:50:36 +01:00
|
|
|
set_no_inheritance (read_ready, val);
|
|
|
|
set_no_inheritance (write_ready, val);
|
2020-04-26 15:38:46 +02:00
|
|
|
set_no_inheritance (writer_opening, val);
|
2019-06-22 16:07:48 +02:00
|
|
|
fifo_client_lock ();
|
2019-04-14 21:15:56 +02:00
|
|
|
for (int i = 0; i < nhandlers; i++)
|
2020-03-16 23:04:28 +01:00
|
|
|
set_no_inheritance (fc_handler[i].h, val);
|
2019-06-22 16:07:48 +02:00
|
|
|
fifo_client_unlock ();
|
2009-07-24 22:54:33 +02:00
|
|
|
}
|