newlib-cygwin/winsup/cygwin/fhandler_fifo.cc

1901 lines
50 KiB
C++
Raw Normal View History

/* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes.
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"
#include <w32api/winioctl.h>
#include "miscfuncs.h"
#include "cygerrno.h"
#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
#include "sigproc.h"
#include "cygtls.h"
* cygprops.h: New file. * dtable.cc (handle_to_fn): Add check for correct installation_key string in object name for pipes and ttys. * external.cc (cygwin_internal): Add CW_GET_INSTKEY to allow fetching the installation_key from cygserver. * fhandler_fifo.cc (fhandler_fifo::fifo_name): Add installation_key to fifo name. * globals.cc: Include cygprops.h. (_RDATA): Move slightly and add comment. (cygwin_props): Define. * mount.cc (mount_info::init): Accommodate the fact that installation_root is now a global variable in DLL common shared memory, rather than a member of cygwin_shared. * pipe.cc (fhandler_pipe::create_selectable): Add installation_key to pipe name. * shared.cc (installation_root): Define here for storage in DLL common shared memory. (installation_key): Ditto. (installation_key_buf): Ditto. (init_installation_root): Convert from shared_info method to ordinary function. Add initializing installation_key. Invalidate installation_key depending of value of disable_key property. Add comment to explain. (get_shared_parent_dir): Add installation_key to directory name. (get_session_parent_dir): Ditto. (shared_info::initialize): Move call to init_installation_root from here... (memory_init): ...to here. Add debug output to print installation root and installation key. Add comment to explain why. * shared_info.h (SHARED_INFO_CB): Recalculate. (CURR_SHARED_MAGIC): Ditto. (class shared_info): Remove definition of installation_root and declaration of init_installation_root. (init_installation_root): Declare. (installation_root): Declare. (installation_key): Declare. * uinfo.cc (pwdgrp::load): Accommodate the fact that installation_root is now a global variable in DLL common shared memory. * include/cygwin/version.h: Bump API minor number. (CYGWIN_INFO_INSTALLATIONS_NAME): Add. * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_GET_INSTKEY.
2009-10-31 21:24:06 +08:00
#include "shared_info.h"
#include "ntdll.h"
#include "cygwait.h"
#include <sys/param.h>
/*
Overview:
FIFOs are implemented via Windows named pipes. The server end of
the pipe corresponds to an fhandler_fifo open for reading (a.k.a,
a "reader"), and the client end corresponds to an fhandler_fifo
open for writing (a.k.a, a "writer").
The server can have multiple instances. The reader (assuming for
the moment that there is only one) creates a pipe instance for
each writer that opens. The reader maintains a list of
"fifo_client_handler" structures, one for each writer. A
fifo_client_handler contains the handle for the pipe server
instance and information about the state of the connection with
the writer. Access to the list is controlled by a
"fifo_client_lock".
The reader runs a "fifo_reader_thread" that creates new pipe
instances as needed and listens for client connections.
The connection state of a fifo_client_handler has one of the
following values, in which order is important:
fc_unknown
fc_error
fc_disconnected
fc_closing
fc_listening
fc_connected
fc_input_avail
It can be changed in the following places:
- It is set to fc_listening when the pipe instance is created.
- It is set to fc_connected when the fifo_reader_thread detects
a connection.
- It is set to a value reported by the O/S when
query_and_set_state is called. This can happen in
select.cc:peek_fifo and a couple other places.
- It is set to fc_disconnected by raw_read when an attempt to
read yields STATUS_PIPE_BROKEN.
- It is set to fc_error in various places when unexpected
things happen.
State changes are always guarded by fifo_client_lock.
If there are multiple readers open, only one of them, called the
"owner", maintains the fifo_client_handler list. The owner is
therefore the only reader that can read at any given time. If a
different reader wants to read, it has to take ownership and
duplicate the fifo_client_handler list.
A reader that is not an owner also runs a fifo_reader_thread,
which is mostly idle. The thread wakes up if that reader might
need to take ownership.
2020-07-12 03:43:44 +08:00
There is a block of named shared memory, accessible to all
fhandlers for a given FIFO. It keeps track of the number of open
readers and writers; it contains information needed for the owner
change process; and it contains some locks to prevent races and
deadlocks between the various threads.
The shared memory is created by the first reader to open the
FIFO. It is opened by subsequent readers and by all writers. It
is destroyed by Windows when the last handle to it is closed.
If a handle to it somehow remains open after all processes
holding file descriptors to the FIFO have closed, the shared
memory can persist and be reused with stale data by the next
process that opens the FIFO. So far I've seen this happen only
as a result of a bug in the code, but there are some debug_printf
statements in fhandler_fifo::open to help detect this if it
happens again.
At this writing, I know of only one application (Midnight
Commander when running under tcsh) that *explicitly* opens two
readers of a FIFO. But many applications will have multiple
readers open via dup/fork/exec.
*/
/* 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; })
#define STATUS_PIPE_NO_INSTANCE_AVAILABLE(status) \
({ NTSTATUS _s = (status); \
_s == STATUS_INSTANCE_NOT_AVAILABLE \
|| _s == STATUS_PIPE_NOT_AVAILABLE \
|| _s == STATUS_PIPE_BUSY; })
/* Number of pages reserved for shared_fc_handler. */
#define SH_FC_HANDLER_PAGES 100
static NO_COPY fifo_reader_id_t null_fr_id = { .winpid = 0, .fh = NULL };
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
fhandler_fifo::fhandler_fifo ():
fhandler_base (),
read_ready (NULL), write_ready (NULL), writer_opening (NULL),
owner_needed_evt (NULL), owner_found_evt (NULL), update_needed_evt (NULL),
cancel_evt (NULL), thr_sync_evt (NULL),
fc_handler (NULL), shandlers (0), nhandlers (0),
reader (false), writer (false), duplexer (false),
max_atomic_write (DEFAULT_PIPEBUFSIZE),
me (null_fr_id), shmem_handle (NULL), shmem (NULL),
shared_fc_hdl (NULL), shared_fc_handler (NULL)
{
pipe_name_buf[0] = L'\0';
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
need_fork_fixup (true);
}
PUNICODE_STRING
fhandler_fifo::get_pipe_name ()
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08: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;
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
}
* cygwin.din (dup3): Export. (pipe2): Export. * dtable.cc (dtable::dup_worker): Take additional flags parameter. Handle O_CLOEXEC flag. (dtable::dup3): Rename from dup2. Take additional flags parameter. Check for valid flags. Drop check for newfd == oldfd. * dtable.h (dtable::dup_worker): Add flags parameter. (dtable::dup3): Rename from dup2. * fcntl.cc (fcntl64): Add F_DUPFD_CLOEXEC case. * fhandler.h (fhandler_mailslot::get_object_attr): Add flags parameter. * fhandler.cc (fhandler_base::open): Use security attribute with inheritance according to setting of O_CLOEXEC flag. * fhandler_console.cc (fhandler_console::open): Ditto. * fhandler_fifo.cc (sec_user_cloexec): New inline function to create security attribute with inheritance according to setting of O_CLOEXEC flag. (fhandler_fifo::open): Call sec_user_cloexec to fetch security attribute. (fhandler_fifo::wait): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_mailslot.cc (fhandler_mailslot::get_object_attr): Take additional flags parameter. Use security attribute with inheritance according to setting of O_CLOEXEC flag. (fhandler_mailslot::open): Call get_object_attr with flags parameter. * fhandler_registry.cc (fhandler_registry::open): Call set_close_on_exec on real handles to accommodate O_CLOEXEC flag. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. * fhandler_tape.cc: Create mutex with inheritance according to setting of O_CLOEXEC flag. * pipe.cc: Replace usage of O_NOINHERIT with O_CLOEXEC. (fhandler_pipe::init): Simplify setting close_on_exec flag. (fhandler_pipe::open): Remove setting close_on_exec flag. (fhandler_pipe::create): Use security attribute with inheritance according to setting of O_CLOEXEC flag. (pipe2): New exported function. * posix_ipc.cc: Throughout, open backing files with O_CLOEXEC flag to follow POSIX semantics. * security.h (sec_none_cloexec): New define. * syscalls.cc (dup): Add missing extern "C" qualifier. Accommodate renaming of dtable::dup2 to dtable::dup3. (dup2): Ditto. Check newfd == oldfd here. (dup3): New function. Check newfd == oldfd here. (open): Set close_on_exec flag according to O_CLOEXEC flag before calling fhandler->open. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
2010-01-15 02:46:02 +08: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);
}
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);
}
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;
}
/* Called when a FIFO is first opened for reading and again each time
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. */
HANDLE
fhandler_fifo::create_pipe_instance ()
{
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;
ULONG max_instances = -1;
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;
hattr = (openflags & O_CLOEXEC ? 0 : OBJ_INHERIT) | OBJ_CASE_INSENSITIVE;
InitializeObjectAttributes (&attr, get_pipe_name (),
hattr, npfsh, NULL);
timeout.QuadPart = -500000;
status = NtCreateNamedPipeFile (&ph, access, &attr, &io, sharing,
FILE_OPEN_IF, 0,
FILE_PIPE_MESSAGE_TYPE
| FILE_PIPE_REJECT_REMOTE_CLIENTS,
FILE_PIPE_MESSAGE_MODE,
nonblocking, max_instances,
DEFAULT_PIPEBUFSIZE, DEFAULT_PIPEBUFSIZE,
&timeout);
if (!NT_SUCCESS (status))
__seterrno_from_nt_status (status);
return ph;
}
/* Connect to a pipe instance. */
NTSTATUS
fhandler_fifo::open_pipe (HANDLE& ph)
{
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;
InitializeObjectAttributes (&attr, get_pipe_name (),
openflags & O_CLOEXEC ? 0 : OBJ_INHERIT,
npfsh, NULL);
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
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);
return status;
}
/* Always called with fifo_client_lock in place. */
int
fhandler_fifo::add_client_handler (bool new_pipe_instance)
{
fifo_client_handler fc;
if (nhandlers >= shandlers)
{
void *temp = realloc (fc_handler,
(shandlers += 64) * sizeof (fc_handler[0]));
if (!temp)
{
shandlers -= 64;
set_errno (ENOMEM);
return -1;
}
fc_handler = (fifo_client_handler *) temp;
}
if (new_pipe_instance)
{
HANDLE ph = create_pipe_instance ();
if (!ph)
return -1;
fc.h = ph;
fc.set_state (fc_listening);
}
fc_handler[nhandlers++] = fc;
return 0;
}
/* Always called with fifo_client_lock in place. Delete a
client_handler by swapping it with the last one in the list. */
void
fhandler_fifo::delete_client_handler (int i)
{
fc_handler[i].close ();
if (i < --nhandlers)
fc_handler[i] = fc_handler[nhandlers];
}
/* Delete handlers that we will never read from. Always called with
fifo_client_lock in place. */
void
fhandler_fifo::cleanup_handlers ()
{
int i = 0;
while (i < nhandlers)
{
if (fc_handler[i].get_state () < fc_connected)
delete_client_handler (i);
else
i++;
}
}
/* Always called with fifo_client_lock in place. */
void
fhandler_fifo::record_connection (fifo_client_handler& fc, bool set,
fifo_client_connect_state s)
{
if (set)
fc.set_state (s);
set_pipe_non_blocking (fc.h, true);
}
/* Called from fifo_reader_thread_func with owner_lock in place. */
int
fhandler_fifo::update_my_handlers ()
{
int ret = 0;
close_all_handlers ();
fifo_reader_id_t prev = get_prev_owner ();
if (!prev)
{
debug_printf ("No previous owner to copy handles from");
return 0;
}
HANDLE prev_proc;
if (prev.winpid == me.winpid)
prev_proc = GetCurrentProcess ();
else
prev_proc = OpenProcess (PROCESS_DUP_HANDLE, false, prev.winpid);
if (!prev_proc)
api_fatal ("Can't open process of previous owner, %E");
fifo_client_lock ();
for (int i = 0; i < get_shared_nhandlers (); i++)
{
if (add_client_handler (false) < 0)
api_fatal ("Can't add client handler, %E");
fifo_client_handler &fc = fc_handler[nhandlers - 1];
if (!DuplicateHandle (prev_proc, shared_fc_handler[i].h,
GetCurrentProcess (), &fc.h, 0,
!close_on_exec (), DUPLICATE_SAME_ACCESS))
{
debug_printf ("Can't duplicate handle of previous owner, %E");
__seterrno ();
fc.set_state (fc_error);
fc.last_read = false;
ret = -1;
}
else
{
fc.set_state (shared_fc_handler[i].get_state ());
fc.last_read = shared_fc_handler[i].last_read;
}
}
fifo_client_unlock ();
set_prev_owner (null_fr_id);
return ret;
}
/* Always called with fifo_client_lock and owner_lock in place. */
int
fhandler_fifo::update_shared_handlers ()
{
cleanup_handlers ();
if (nhandlers > get_shared_shandlers ())
{
if (remap_shared_fc_handler (nhandlers * sizeof (fc_handler[0])) < 0)
return -1;
}
set_shared_nhandlers (nhandlers);
memcpy (shared_fc_handler, fc_handler, nhandlers * sizeof (fc_handler[0]));
shared_fc_handler_updated (true);
set_prev_owner (me);
return 0;
}
static DWORD WINAPI
fifo_reader_thread (LPVOID param)
{
fhandler_fifo *fh = (fhandler_fifo *) param;
return fh->fifo_reader_thread_func ();
}
DWORD
fhandler_fifo::fifo_reader_thread_func ()
{
HANDLE conn_evt;
if (!(conn_evt = CreateEvent (NULL, false, false, NULL)))
api_fatal ("Can't create connection event, %E");
while (1)
{
fifo_reader_id_t cur_owner, pending_owner;
bool idle = false, take_ownership = false;
owner_lock ();
cur_owner = get_owner ();
pending_owner = get_pending_owner ();
if (pending_owner)
{
if (pending_owner == me)
take_ownership = true;
else if (cur_owner != me)
idle = true;
else
{
/* I'm the owner but someone else wants to be. Have I
already seen and reacted to update_needed_evt? */
if (WaitForSingleObject (update_needed_evt, 0) == WAIT_OBJECT_0)
{
/* No, I haven't. */
fifo_client_lock ();
if (update_shared_handlers () < 0)
api_fatal ("Can't update shared handlers, %E");
fifo_client_unlock ();
}
owner_unlock ();
/* Yield to pending owner. */
Sleep (1);
continue;
}
}
else if (!cur_owner)
take_ownership = true;
else if (cur_owner != me)
idle = true;
else
/* I'm the owner and there's no pending owner. */
goto owner_listen;
if (idle)
{
owner_unlock ();
HANDLE w[2] = { owner_needed_evt, cancel_evt };
switch (WaitForMultipleObjects (2, w, false, INFINITE))
{
case WAIT_OBJECT_0:
continue;
case WAIT_OBJECT_0 + 1:
goto canceled;
default:
api_fatal ("WFMO failed, %E");
}
}
else if (take_ownership)
{
if (!shared_fc_handler_updated ())
{
owner_unlock ();
if (IsEventSignalled (cancel_evt))
goto canceled;
continue;
}
else
{
set_owner (me);
set_pending_owner (null_fr_id);
if (update_my_handlers () < 0)
debug_printf ("error updating my handlers, %E");
owner_found ();
/* Fall through to owner_listen. */
}
}
owner_listen:
2020-07-12 02:55:39 +08:00
fifo_client_lock ();
cleanup_handlers ();
if (add_client_handler () < 0)
api_fatal ("Can't add a client handler, %E");
/* Listen for a writer to connect to the new client handler. */
fifo_client_handler& fc = fc_handler[nhandlers - 1];
fifo_client_unlock ();
shared_fc_handler_updated (false);
owner_unlock ();
NTSTATUS status;
IO_STATUS_BLOCK io;
bool cancel = false;
bool update = false;
status = NtFsControlFile (fc.h, conn_evt, NULL, NULL, &io,
FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
if (status == STATUS_PENDING)
{
HANDLE w[3] = { conn_evt, update_needed_evt, cancel_evt };
switch (WaitForMultipleObjects (3, w, false, INFINITE))
{
2020-07-12 02:55:39 +08:00
case WAIT_OBJECT_0:
status = io.Status;
debug_printf ("NtFsControlFile STATUS_PENDING, then %y",
status);
break;
2020-07-12 02:55:39 +08:00
case WAIT_OBJECT_0 + 1:
status = STATUS_WAIT_1;
update = true;
break;
2020-07-12 02:55:39 +08:00
case WAIT_OBJECT_0 + 2:
status = STATUS_THREAD_IS_TERMINATING;
cancel = true;
update = true;
break;
default:
2020-07-12 02:55:39 +08:00
api_fatal ("WFMO failed, %E");
}
2020-07-12 02:55:39 +08:00
}
else
debug_printf ("NtFsControlFile status %y, no STATUS_PENDING",
status);
HANDLE ph = NULL;
NTSTATUS status1;
fifo_client_lock ();
if (fc.get_state () != fc_listening)
/* select.cc:peek_fifo has already recorded a connection. */
;
else
2020-07-12 02:55:39 +08:00
{
2020-08-03 21:43:36 +08:00
switch (status)
{
case STATUS_SUCCESS:
case STATUS_PIPE_CONNECTED:
record_connection (fc);
break;
case STATUS_PIPE_CLOSING:
debug_printf ("NtFsControlFile got STATUS_PIPE_CLOSING...");
/* Maybe a writer already connected, wrote, and closed.
Just query the O/S. */
fc.query_and_set_state ();
debug_printf ("...O/S reports state %d", fc.get_state ());
record_connection (fc, false);
break;
case STATUS_THREAD_IS_TERMINATING:
case STATUS_WAIT_1:
/* 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);
else
/* Did a real client connect? */
switch (io.Status)
{
case STATUS_SUCCESS:
case STATUS_PIPE_CONNECTED:
record_connection (fc);
break;
case STATUS_PIPE_CLOSING:
debug_printf ("got STATUS_PIPE_CLOSING when trying to connect bogus client...");
fc.query_and_set_state ();
debug_printf ("...O/S reports state %d", fc.get_state ());
record_connection (fc, false);
break;
default:
debug_printf ("NtFsControlFile status %y after failing to connect bogus client or real client", io.Status);
fc.set_state (fc_error);
break;
}
break;
default:
debug_printf ("NtFsControlFile got unexpected status %y", status);
fc.set_state (fc_error);
break;
}
2020-07-12 02:55:39 +08:00
}
if (ph)
NtClose (ph);
if (update)
{
owner_lock ();
if (get_owner () == me && update_shared_handlers () < 0)
api_fatal ("Can't update shared handlers, %E");
owner_unlock ();
}
2020-07-12 02:55:39 +08:00
fifo_client_unlock ();
if (cancel)
goto canceled;
}
canceled:
if (conn_evt)
NtClose (conn_evt);
/* automatically return the cygthread to the cygthread pool */
_my_tls._ctinfo->auto_release ();
return 0;
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* Return -1 on error and 0 or 1 on success. If ONLY_OPEN is true, we
expect the shared memory to exist, and we only try to open it. In
this case, we return 0 on success.
Otherwise, we create the shared memory if it doesn't exist, and we
return 1 if it already existed and we successfully open it. */
int
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
fhandler_fifo::create_shmem (bool only_open)
{
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];
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
bool already_exists = false;
__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);
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (!only_open)
{
status = NtCreateSection (&sect, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
| SECTION_MAP_READ | SECTION_MAP_WRITE,
&attr, &size, PAGE_READWRITE, SEC_COMMIT, NULL);
if (status == STATUS_OBJECT_NAME_COLLISION)
already_exists = true;
}
if (only_open || already_exists)
status = NtOpenSection (&sect, 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;
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
return already_exists ? 1 : 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;
}
/* On first creation, map and commit one page of memory. */
int
fhandler_fifo::create_shared_fc_handler ()
{
HANDLE sect;
OBJECT_ATTRIBUTES attr;
NTSTATUS status;
LARGE_INTEGER size
= { .QuadPart = (LONGLONG) (SH_FC_HANDLER_PAGES * wincap.page_size ()) };
SIZE_T viewsize = get_shared_fc_handler_committed () ?: wincap.page_size ();
PVOID addr = NULL;
UNICODE_STRING uname;
WCHAR shared_fc_name[MAX_PATH];
__small_swprintf (shared_fc_name, L"fifo-shared-fc.%08x.%016X", get_dev (),
get_ino ());
RtlInitUnicodeString (&uname, shared_fc_name);
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT,
get_shared_parent_dir (), NULL);
status = NtCreateSection (&sect, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
| SECTION_MAP_READ | SECTION_MAP_WRITE, &attr,
&size, PAGE_READWRITE, SEC_RESERVE, NULL);
if (status == STATUS_OBJECT_NAME_COLLISION)
status = NtOpenSection (&sect, 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;
}
shared_fc_hdl = sect;
shared_fc_handler = (fifo_client_handler *) addr;
if (!get_shared_fc_handler_committed ())
set_shared_fc_handler_committed (viewsize);
set_shared_shandlers (viewsize / sizeof (fifo_client_handler));
return 0;
}
/* shared_fc_hdl must be valid when this is called. */
int
fhandler_fifo::reopen_shared_fc_handler ()
{
NTSTATUS status;
SIZE_T viewsize = get_shared_fc_handler_committed ();
PVOID addr = NULL;
status = NtMapViewOfSection (shared_fc_hdl, NtCurrentProcess (),
&addr, 0, viewsize, NULL, &viewsize,
ViewShare, 0, PAGE_READWRITE);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return -1;
}
shared_fc_handler = (fifo_client_handler *) addr;
return 0;
}
int
fhandler_fifo::remap_shared_fc_handler (size_t nbytes)
{
NTSTATUS status;
SIZE_T viewsize = roundup2 (nbytes, wincap.page_size ());
PVOID addr = NULL;
if (viewsize > SH_FC_HANDLER_PAGES * wincap.page_size ())
{
set_errno (ENOMEM);
return -1;
}
NtUnmapViewOfSection (NtCurrentProcess (), shared_fc_handler);
status = NtMapViewOfSection (shared_fc_hdl, NtCurrentProcess (),
&addr, 0, viewsize, NULL, &viewsize,
ViewShare, 0, PAGE_READWRITE);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return -1;
}
shared_fc_handler = (fifo_client_handler *) addr;
set_shared_fc_handler_committed (viewsize);
set_shared_shandlers (viewsize / sizeof (fc_handler[0]));
return 0;
}
int
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
fhandler_fifo::open (int flags, mode_t)
{
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
int saved_errno = 0, shmem_res = 0;
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
if (flags & O_PATH)
return open_fs (flags);
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
/* Determine what we're doing with this fhandler: reading, writing, both */
switch (flags & O_ACCMODE)
{
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
case O_RDONLY:
reader = true;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
break;
case O_WRONLY:
writer = true;
break;
case O_RDWR:
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
reader = writer = duplexer = true;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
break;
default:
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
set_errno (EINVAL);
goto err;
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
}
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
debug_only_printf ("reader %d, writer %d, duplexer %d", reader, writer, duplexer);
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
set_flags (flags);
if (reader && !duplexer)
nohandle (true);
/* Create control events for this named pipe */
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08: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());
char npbuf[MAX_PATH];
__small_sprintf (npbuf, "r-event.%08x.%016X", get_dev (), get_ino ());
if (!(read_ready = CreateEvent (sa_buf, true, false, npbuf)))
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
{
debug_printf ("CreateEvent for %s failed, %E", npbuf);
__seterrno ();
goto err;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
}
npbuf[0] = 'w';
if (!(write_ready = CreateEvent (sa_buf, true, false, npbuf)))
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
{
debug_printf ("CreateEvent for %s failed, %E", npbuf);
__seterrno ();
goto err_close_read_ready;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
}
npbuf[0] = 'o';
if (!(writer_opening = CreateEvent (sa_buf, true, false, npbuf)))
{
debug_printf ("CreateEvent for %s failed, %E", npbuf);
__seterrno ();
goto err_close_write_ready;
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* If we're reading, create the shared memory and the shared
fc_handler memory, create some events, start the
fifo_reader_thread, signal read_ready, and wait for a writer. */
if (reader)
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
{
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* Create/open shared memory. */
if ((shmem_res = create_shmem ()) < 0)
goto err_close_writer_opening;
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
else if (shmem_res == 0)
debug_printf ("shmem created");
else
debug_printf ("shmem existed; ok if we're not the first reader");
if (create_shared_fc_handler () < 0)
goto err_close_shmem;
npbuf[0] = 'n';
if (!(owner_needed_evt = CreateEvent (sa_buf, true, false, npbuf)))
{
debug_printf ("CreateEvent for %s failed, %E", npbuf);
__seterrno ();
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
goto err_close_shared_fc_handler;
}
npbuf[0] = 'f';
if (!(owner_found_evt = CreateEvent (sa_buf, true, false, npbuf)))
{
debug_printf ("CreateEvent for %s failed, %E", npbuf);
__seterrno ();
goto err_close_owner_needed_evt;
}
npbuf[0] = 'u';
if (!(update_needed_evt = CreateEvent (sa_buf, false, false, npbuf)))
{
debug_printf ("CreateEvent for %s failed, %E", npbuf);
__seterrno ();
goto err_close_owner_found_evt;
}
if (!(cancel_evt = create_event ()))
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
goto err_close_update_needed_evt;
if (!(thr_sync_evt = create_event ()))
goto err_close_cancel_evt;
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
me.winpid = GetCurrentProcessId ();
me.fh = this;
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
nreaders_lock ();
if (inc_nreaders () == 1)
{
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* Reinitialize _sh_fc_handler_updated, which starts as 0. */
shared_fc_handler_updated (true);
set_owner (me);
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
SetEvent (read_ready);
nreaders_unlock ();
/* If we're a duplexer, we need a handle for writing. */
if (duplexer)
{
HANDLE ph = NULL;
NTSTATUS status;
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
nwriters_lock ();
inc_nwriters ();
SetEvent (write_ready);
nwriters_unlock ();
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);
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
nohandle (true);
goto err_close_reader;
}
}
}
/* Not a duplexer; wait for a writer to connect if we're blocking. */
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
else if (!wait (write_ready))
goto err_close_reader;
goto success;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* If we're writing, wait for read_ready, connect to the pipe, open
the shared memory, and signal write_ready. */
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
if (writer)
{
NTSTATUS status;
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* Don't let a reader see EOF at this point. */
SetEvent (writer_opening);
while (1)
{
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (!wait (read_ready))
{
ResetEvent (writer_opening);
goto err_close_writer_opening;
}
status = open_pipe (get_handle ());
if (NT_SUCCESS (status))
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
goto writer_shmem;
else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* The pipe hasn't been created yet or there's no longer
a reader open. */
yield ();
continue;
}
else if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status))
break;
else
{
debug_printf ("create of writer failed");
__seterrno_from_nt_status (status);
ResetEvent (writer_opening);
goto err_close_writer_opening;
}
}
/* We should get here only if the system is heavily loaded
and/or many writers are trying to connect simultaneously */
while (1)
{
if (!wait (read_ready))
{
ResetEvent (writer_opening);
goto err_close_writer_opening;
}
status = wait_open_pipe (get_handle ());
if (NT_SUCCESS (status))
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
goto writer_shmem;
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;
}
}
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
writer_shmem:
if (create_shmem (true) < 0)
goto err_close_writer_opening;
/* writer_success: */
set_pipe_non_blocking (get_handle (), flags & O_NONBLOCK);
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
nwriters_lock ();
inc_nwriters ();
SetEvent (write_ready);
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
ResetEvent (writer_opening);
nwriters_unlock ();
success:
return 1;
err_close_reader:
saved_errno = get_errno ();
close ();
set_errno (saved_errno);
return 0;
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
/* err_close_thr_sync_evt: */
/* NtClose (thr_sync_evt); */
err_close_cancel_evt:
NtClose (cancel_evt);
err_close_update_needed_evt:
NtClose (update_needed_evt);
err_close_owner_found_evt:
NtClose (owner_found_evt);
err_close_owner_needed_evt:
NtClose (owner_needed_evt);
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
err_close_shared_fc_handler:
NtUnmapViewOfSection (NtCurrentProcess (), shared_fc_handler);
NtClose (shared_fc_hdl);
err_close_shmem:
NtUnmapViewOfSection (NtCurrentProcess (), shmem);
NtClose (shmem_handle);
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;
}
off_t
fhandler_fifo::lseek (off_t offset, int whence)
{
debug_printf ("(%D, %d)", offset, whence);
set_errno (ESPIPE);
return -1;
}
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
bool
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
fhandler_fifo::wait (HANDLE h)
{
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
#ifdef DEBUGGING
const char *what;
if (h == read_ready)
what = "reader";
else
what = "writer";
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08: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. */
switch (cygwait (h, wait))
{
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
case WAIT_OBJECT_0:
debug_only_printf ("successfully waited for %s", what);
return true;
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;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
case WAIT_TIMEOUT:
if (h == write_ready)
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
{
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
debug_only_printf ("wait timed out waiting for write but will still open reader since non-blocking mode");
return true;
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
}
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
else
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
{
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
set_errno (ENXIO);
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
return false;
}
break;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
default:
debug_only_printf ("unknown error while waiting for %s", what);
__seterrno ();
return false;
}
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
}
ssize_t __reg3
fhandler_fifo::raw_write (const void *ptr, size_t len)
{
ssize_t ret = -1;
size_t nbytes = 0;
ULONG chunk;
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK io;
HANDLE evt = NULL;
if (!len)
return 0;
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)))
{
__seterrno ();
return -1;
}
/* 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)
{
ULONG_PTR nbytes_now = 0;
size_t left = len - nbytes;
ULONG len1;
DWORD waitret = WAIT_OBJECT_0;
if (left > chunk)
len1 = chunk;
else
len1 = (ULONG) left;
nbytes_now = 0;
status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
(PVOID) ptr, len1, NULL, NULL);
if (evt && status == STATUS_PENDING)
{
waitret = cygwait (evt);
if (waitret == WAIT_OBJECT_0)
status = io.Status;
}
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))
{
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;
}
if (evt)
NtClose (evt);
if (status == STATUS_THREAD_SIGNALED && ret < 0)
set_errno (EINTR);
else if (status == STATUS_THREAD_CANCELED)
pthread::static_cancel_self ();
return ret;
}
/* Called from raw_read and select.cc:peek_fifo. */
int
fhandler_fifo::take_ownership (DWORD timeout)
{
int ret = 0;
owner_lock ();
if (get_owner () == me)
{
owner_unlock ();
return 0;
}
set_pending_owner (me);
/* Wake up my fifo_reader_thread. */
owner_needed ();
if (get_owner ())
/* Wake up the owner and request an update of the shared fc_handlers. */
SetEvent (update_needed_evt);
owner_unlock ();
/* The reader threads should now do the transfer. */
switch (WaitForSingleObject (owner_found_evt, timeout))
{
case WAIT_OBJECT_0:
owner_lock ();
if (get_owner () != me)
{
debug_printf ("owner_found_evt signaled, but I'm not the owner");
ret = -1;
}
owner_unlock ();
break;
case WAIT_TIMEOUT:
debug_printf ("timed out");
ret = -1;
break;
default:
debug_printf ("WFSO failed, %E");
ret = -1;
break;
}
return ret;
}
void __reg3
fhandler_fifo::raw_read (void *in_ptr, size_t& len)
Preliminary change to make fifos/pipes interruptible and fifos reliable. * dtable.cc (dtable::find_fifo): Eliminate definition. * dtable.h (dtable::find_fifo): Ditto for declaration. * fhandler.cc (fhandler_base::raw_read): Remove pipe-specific stuff. (fhandler_base::fhandler_base): Ditto. (fhandler_base::close): Handle overlapped I/O structure if appropriate. (fhandler_base::dup): Ditto. (fhandler_base::fork_fixup): Ditto. (fhandler_base::setup_overlapped): Define new function. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. * fhandler.h (fhandler_base::get_overlapped): Declare new function. (fhandler_base::setup_overlapped): Ditto. (fhandler_base::destroy_overlapped): Ditto. (fhandler_base::wait_overlapped): Ditto. (fhandler_base::read_overlapped): Ditto. (fhandler_base::write_overlapped): Ditto. (fhandler_base::get_guard): Eliminate. (fhandler_pipe::*): Rework to eliminate most Win9x related cruft, removing many variables and defining a new overlapped capability. (fhandler_fifo::*): Ditto. (fifo_state): Declare new enum. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove old Win9x stuff. Initialize overlapped handle to NULL. (fhandler_fifo::set_use): Eliminate. (fhandler_fifo::open_nonserver): Define. (fhandler_fifo::open): Rework to use named pipes and overlapped I/O. (fhandler_fifo::wait): Define new function to wait for named pipe connection. (fhandler_fifo::read): Rework to use wait() and new overlapped I/O functionality. (fhandler_fifo::write): Ditto. (fhandler_fifo::dup): Eliminate. * pinfo.cc (commune_process): Remove fifo handling. (_pinfo::commune_request): Ditto. * pinfo.h (picom): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Remove Win9x stuff. Initialize overlapped handle to NULL. (fhandler_pipe::open): Eliminate Win9x stuff. (fhandler_pipe::set_close_on_exec): Eliminate. (read_pipe): Eliminate. (fhandler_pipe::close): Ditto. (fhandler_pipe::fixup_after_exec): Ditto. (fhandler_pipe::fixup_in_child): Ditto. (fhandler_pipe::read): Rework to use overlapped I/O. (fhandler_pipe::write): New function using overlapped I/O. (fhandler_pipe::dup): Rework to eliminate Win9x stuff. (fhandler_pipe::create_selectable): Rework to eliminate Win9x and use overlapped I/O. * select.cc (peek_pipe): Rework to eliminate Win9x stuff and use overlapped I/O. (fhandler_base::ready_for_read): Ditto.
2007-07-08 01:00:33 +08:00
{
if (!len)
return;
while (1)
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
{
int nconnected = 0;
/* No one else can take ownership while we hold the reading_lock. */
reading_lock ();
if (take_ownership (10) < 0)
goto maybe_retry;
fifo_client_lock ();
/* Poll the connected clients for input. Make three passes.
On the first pass, just try to read from the client from
which we last read successfully. This should minimize
interleaving of writes from different clients.
On the second pass, just try to read from the clients in the
state fc_input_avail. This should be more efficient if
select has been called and detected input available.
On the third pass, try to read from all connected clients. */
/* First pass. */
int j;
for (j = 0; j < nhandlers; j++)
if (fc_handler[j].last_read)
break;
if (j < nhandlers && fc_handler[j].get_state () < fc_connected)
{
fc_handler[j].last_read = false;
j = nhandlers;
}
if (j < nhandlers)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
status = NtReadFile (fc_handler[j].h, NULL, NULL, NULL,
&io, in_ptr, len, NULL, NULL);
switch (status)
{
case STATUS_SUCCESS:
case STATUS_BUFFER_OVERFLOW:
/* io.Information is supposedly valid in latter case. */
if (io.Information > 0)
{
len = io.Information;
fifo_client_unlock ();
reading_unlock ();
return;
}
break;
case STATUS_PIPE_EMPTY:
/* Update state in case it's fc_input_avail. */
fc_handler[j].set_state (fc_connected);
break;
case STATUS_PIPE_BROKEN:
fc_handler[j].set_state (fc_disconnected);
break;
default:
debug_printf ("NtReadFile status %y", status);
fc_handler[j].set_state (fc_error);
break;
}
}
/* Second pass. */
for (int i = 0; i < nhandlers; i++)
if (fc_handler[i].get_state () == fc_input_avail)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
status = NtReadFile (fc_handler[i].h, NULL, NULL, NULL,
&io, in_ptr, len, NULL, NULL);
switch (status)
{
case STATUS_SUCCESS:
case STATUS_BUFFER_OVERFLOW:
if (io.Information > 0)
{
len = io.Information;
if (j < nhandlers)
fc_handler[j].last_read = false;
fc_handler[i].last_read = true;
fifo_client_unlock ();
reading_unlock ();
return;
}
break;
case STATUS_PIPE_EMPTY:
/* No input available after all. */
fc_handler[i].set_state (fc_connected);
break;
case STATUS_PIPE_BROKEN:
fc_handler[i].set_state (fc_disconnected);
break;
default:
debug_printf ("NtReadFile status %y", status);
fc_handler[i].set_state (fc_error);
break;
}
}
/* Third pass. */
for (int i = 0; i < nhandlers; i++)
if (fc_handler[i].get_state () >= fc_connected)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
nconnected++;
status = NtReadFile (fc_handler[i].h, NULL, NULL, NULL,
&io, in_ptr, len, NULL, NULL);
switch (status)
{
case STATUS_SUCCESS:
case STATUS_BUFFER_OVERFLOW:
if (io.Information > 0)
{
len = io.Information;
if (j < nhandlers)
fc_handler[j].last_read = false;
fc_handler[i].last_read = true;
fifo_client_unlock ();
reading_unlock ();
return;
}
break;
case STATUS_PIPE_EMPTY:
break;
case STATUS_PIPE_BROKEN:
fc_handler[i].set_state (fc_disconnected);
nconnected--;
break;
default:
debug_printf ("NtReadFile status %y", status);
fc_handler[i].set_state (fc_error);
nconnected--;
break;
}
}
fifo_client_unlock ();
if (!nconnected && hit_eof ())
{
reading_unlock ();
len = 0;
return;
}
maybe_retry:
reading_unlock ();
if (is_nonblocking ())
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
{
set_errno (EAGAIN);
goto errout;
}
else
{
/* Allow interruption and don't hog the CPU. */
DWORD waitret = cygwait (NULL, 1, cw_cancel | cw_sig_eintr);
if (waitret == WAIT_CANCELED)
pthread::static_cancel_self ();
else if (waitret == WAIT_SIGNALED)
{
if (_my_tls.call_signal_handler ())
continue;
else
{
set_errno (EINTR);
goto errout;
}
}
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
}
/* We might have been closed by a signal handler or another thread. */
if (isclosed ())
{
set_errno (EBADF);
goto errout;
}
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
}
errout:
len = (size_t) -1;
}
int __reg2
fhandler_fifo::fstatvfs (struct statvfs *sfs)
{
if (get_flags () & O_PATH)
/* We already have a handle. */
{
HANDLE h = get_handle ();
if (h)
return fstatvfs_by_handle (h, sfs);
}
fhandler_disk_file fh (pc);
fh.get_device () = FH_FS;
return fh.fstatvfs (sfs);
}
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
void
fhandler_fifo::close_all_handlers ()
{
fifo_client_lock ();
for (int i = 0; i < nhandlers; i++)
fc_handler[i].close ();
nhandlers = 0;
fifo_client_unlock ();
}
/* Return previous state. */
fifo_client_connect_state
fifo_client_handler::query_and_set_state ()
{
IO_STATUS_BLOCK io;
FILE_PIPE_LOCAL_INFORMATION fpli;
NTSTATUS status;
fifo_client_connect_state prev_state = get_state ();
if (!h)
{
set_state (fc_unknown);
goto out;
}
status = NtQueryInformationFile (h, &io, &fpli,
sizeof (fpli), FilePipeLocalInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("NtQueryInformationFile status %y", status);
set_state (fc_error);
}
else if (fpli.ReadDataAvailable > 0)
set_state (fc_input_avail);
else
switch (fpli.NamedPipeState)
{
case FILE_PIPE_DISCONNECTED_STATE:
set_state (fc_disconnected);
break;
case FILE_PIPE_LISTENING_STATE:
set_state (fc_listening);
break;
case FILE_PIPE_CONNECTED_STATE:
set_state (fc_connected);
break;
case FILE_PIPE_CLOSING_STATE:
set_state (fc_closing);
break;
default:
set_state (fc_error);
break;
}
out:
return prev_state;
}
void
fhandler_fifo::cancel_reader_thread ()
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
{
if (cancel_evt)
SetEvent (cancel_evt);
if (thr_sync_evt)
WaitForSingleObject (thr_sync_evt, INFINITE);
}
int
fhandler_fifo::close ()
{
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (writer)
{
nwriters_lock ();
if (dec_nwriters () == 0)
ResetEvent (write_ready);
nwriters_unlock ();
}
if (reader)
{
/* If we're the owner, we can't close our fc_handlers if a new
owner might need to duplicate them. */
bool close_fc_ok = false;
cancel_reader_thread ();
nreaders_lock ();
if (dec_nreaders () == 0)
{
close_fc_ok = true;
ResetEvent (read_ready);
ResetEvent (owner_needed_evt);
ResetEvent (owner_found_evt);
set_owner (null_fr_id);
set_prev_owner (null_fr_id);
set_pending_owner (null_fr_id);
set_shared_nhandlers (0);
}
else
{
owner_lock ();
if (get_owner () != me)
close_fc_ok = true;
else
{
set_owner (null_fr_id);
set_prev_owner (me);
if (!get_pending_owner ())
owner_needed ();
}
owner_unlock ();
}
nreaders_unlock ();
while (!close_fc_ok)
{
if (WaitForSingleObject (owner_found_evt, 1) == WAIT_OBJECT_0)
close_fc_ok = true;
else
{
nreaders_lock ();
if (!nreaders ())
{
close_fc_ok = true;
nreaders_unlock ();
}
else
{
nreaders_unlock ();
owner_lock ();
if (get_owner () || get_prev_owner () != me)
close_fc_ok = true;
owner_unlock ();
}
}
}
close_all_handlers ();
if (fc_handler)
free (fc_handler);
if (owner_needed_evt)
NtClose (owner_needed_evt);
if (owner_found_evt)
NtClose (owner_found_evt);
if (update_needed_evt)
NtClose (update_needed_evt);
if (cancel_evt)
NtClose (cancel_evt);
if (thr_sync_evt)
NtClose (thr_sync_evt);
if (shared_fc_handler)
NtUnmapViewOfSection (NtCurrentProcess (), shared_fc_handler);
if (shared_fc_hdl)
NtClose (shared_fc_hdl);
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (shmem)
NtUnmapViewOfSection (NtCurrentProcess (), shmem);
if (shmem_handle)
NtClose (shmem_handle);
if (read_ready)
NtClose (read_ready);
if (write_ready)
NtClose (write_ready);
if (writer_opening)
NtClose (writer_opening);
if (nohandle ())
return 0;
else
return fhandler_base::close ();
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08: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. */
int
fhandler_fifo::fcntl (int cmd, intptr_t arg)
{
if (cmd != F_SETFL || nohandle () || (get_flags () & O_PATH))
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;
}
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
int
* cygerrno.h (__set_errno): Modify debugging output to make searching strace logs easier. Throughout, change /dev/tty* to /dev/pty*. Throughout, add flags argument to fhandler_*::dup methods. * devices.in: Rename (temporarily?) /dev/ttyN to /dev/ptyN. Add /dev/ptymN devices for pty masters. * devices.cc: Regenerate. * devices.h (MAX_CONSOLES): Set to max number supported by devices.in. (fh_devices::FH_PTMX): Rename from FH_PTYM. (device::operator int): Return by reference. * dtable.cc (fh_alloc): Take pc as an argument rather than just the device. This makes debugging easier since more information is available. Actually implement handling for already-allocated pty master devices. Make different decisions when generating fhandler for not-opened devices. Add kludge to deal with opening /dev/tty. (cnew_no_ctor): New macro. (build_fh_pc): Make debugging output more verbose. Use new clone() fhandler interface to duplicate archetypes. Reset last term opened. (dtable::dup_worker): Use Use new clone() fhandler interface to duplicate archetypes. Pass flags to child dup handler. (dtable::dup3): Set O_NOCTTY flag if newfd is not stdin/stdout/stderr. * fhandler.cc (fhandler_base::reset): Rename from operator =() and reduce functionality and sense of copy direction. (fhandler_base::open_with_arch): Use published interface to query io_handle(). Use new copyto() fhandler method to copy from/to found archetype. * fhandler.h: Throughout, delete size(), add copyout, clone, and fhandler_* (void *) methods. (fhandler_base::reset): Rename from operator =(). (fhandler_termios::is_dev_tty): Delete. (fhandler_termios): change "protected" region to "private". (fhandler_termios::is_dev_tty): Delete. (fhandler_termios): Rearrange protected/public. (fhandler_termios::fhandler_termios): Remember last fhandler_termios "opened". (fhandler_termios::~fhandler_termios): Forget last fhandler_termios opened. (ioctl): Rename from ioctl_termios. Take a void * argument. Reflect argument change in pinfo::set_ctty. (fhandler_console::dup): Declare new function. Set ctty here if appropriate. (fhandler_pty_master::from_master): Privatize. (fhandler_pty_master::to_master): Ditto. (fhandler_pty_master::dwProcessId): Ditto. (fhandler_pty_master::fhandler_pty_master): Add an `int' argument. (fhandler_pty_master::open_setup): Declare new function. (fhandler_pty_master::~fhandler_pty_master): Declare new method. (fhandler_nodevice): Remove commented out function declaration. * fhandler_console.cc: Use get_ttyp() instead of tc() throughout. (fhandler_console::dup): Define new function to set controlling ctty on dup, as appropriate. (fhandler_console::ioctl): Reflect ioctl_termios name change. (fhandler_console::setup): Rename from get_tty_stuff. (fhandler_console::open_setup): Reflect argument change in pinfo::set_ctty. (fhandler_console::fhandler_console): Set _tc here. * fhandler_termios.cc (handler_termios::ioctl): Rename. Take a void * arg like other ioctl functions. * fhandler_tty.cc (fhandler_pty_slave::dup): Call myself->set_ctty to potentially reset the controlling terminal. (fhandler_pty_slave::ioctl): Reflect name/arg change for ioctl_termios. (fhandler_pty_slave::fhandler_pty_slave): Take a "unit" argument. Call setup() here so that we will know the unit number of this fhandler as soon as possible. Set the unit as appropriate. (handler_pty_master::open): Move most stuff to constructor and open_setup. (handler_pty_slave::open_setup): Reflect argument change in pinfo::set_ctty. (handler_pty_master::open_setup): Define new function. (fhandler_pty_master::cleanup): Clear handles as a flag that the destructor does not have to do "close" operations. (fhandler_pty_master::close): Ditto. (fhandler_pty_master::~fhandler_pty_master): Define new method. (fhandler_pty_master::ioctl): Reflect name/arg change for ioctl_termios. (fhandler_pty_master::setup): Allocate tty here. Rely on handles being returned from allocated test rather than opening them here. Avoid setting _need_nl here since it is already zeroed in the constructor. Set up device information with DEV_TTYM_MAJOR. * path.h (path_conv &operator =): Take a const argument. (path_conv::dup): Ditto. (pathconv_arg::PC_OPEN): New enum. (pathconv_arg::PC_CTTY): Ditto. (path_types::PATH_CTTY): Ditto. (path_types::PATH_OPEN): Ditto. (path_conv::isopen): New method. (path_conv::isctty_capable): Ditto. * path.cc (path_conv::check): Set PATH_OPEN and PATH_CTTY as appropriate. * pipe.cc (fhandler_pipe::open): Use copyto to copy pipe handle. * syscall.cc (open): Reinstate fd > 2 check to disallow resetting ctty on non-std* handles. * tty.cc (tty_list::allocate): Pass out handles for allocated tty. use `not_allocated' to find unallocated ttys. Avoid keeping the lock since the allocation of the tty should be sufficient to prevent multiple access. (tty::not_allocated): Clarify comment. Rename. Return handles when an unused tty is found. Simply test for existing tty. (tty::exists): Rewrite to use `not_allocated'. * tty.h (NTTYS): Reset down to actual number supported by devices.in. (tty::not_allocated): Declare new function. (tty_list::allocate): Pass out read/write tty handles. Zero them when not found. * fhandler_proc.cc: Reflect name change from FH_PTYM -> FH_PTMX. * pinfo.h (pinfo::set_ctty): Reduce/reorder arguments passed in. * pinfo.cc (pinfo::set_ctty): Ditto. Just use tc() built into the passed-in fhandler_termios pointer. Return true if ctty is assigned. * syscalls.cc (open): Call build_fh_pc with PC_OPEN flag. Set PC_CTTY if appropriate. (stat_worker): Remove is_dev_tty () stuff.
2011-10-16 06:37:30 +08:00
fhandler_fifo::dup (fhandler_base *child, int flags)
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
{
fhandler_fifo *fhf = NULL;
if (get_flags () & O_PATH)
return fhandler_base::dup (child, flags);
if (fhandler_base::dup (child, flags))
goto err;
fhf = (fhandler_fifo *) child;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
if (!DuplicateHandle (GetCurrentProcess (), read_ready,
GetCurrentProcess (), &fhf->read_ready,
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
{
__seterrno ();
goto err;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
}
if (!DuplicateHandle (GetCurrentProcess (), write_ready,
GetCurrentProcess (), &fhf->write_ready,
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
{
__seterrno ();
goto err_close_read_ready;
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
}
if (!DuplicateHandle (GetCurrentProcess (), writer_opening,
GetCurrentProcess (), &fhf->writer_opening,
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
{
__seterrno ();
goto err_close_write_ready;
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08: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;
if (reader)
{
/* Make sure the child starts unlocked. */
fhf->fifo_client_unlock ();
/* Clear fc_handler list; the child never starts as owner. */
fhf->nhandlers = fhf->shandlers = 0;
fhf->fc_handler = NULL;
if (!DuplicateHandle (GetCurrentProcess (), shared_fc_hdl,
GetCurrentProcess (), &fhf->shared_fc_hdl,
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
{
__seterrno ();
goto err_close_shmem;
}
if (fhf->reopen_shared_fc_handler () < 0)
goto err_close_shared_fc_hdl;
if (!DuplicateHandle (GetCurrentProcess (), owner_needed_evt,
GetCurrentProcess (), &fhf->owner_needed_evt,
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
{
__seterrno ();
goto err_close_shared_fc_handler;
}
if (!DuplicateHandle (GetCurrentProcess (), owner_found_evt,
GetCurrentProcess (), &fhf->owner_found_evt,
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
{
__seterrno ();
goto err_close_owner_needed_evt;
}
if (!DuplicateHandle (GetCurrentProcess (), update_needed_evt,
GetCurrentProcess (), &fhf->update_needed_evt,
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
{
__seterrno ();
goto err_close_owner_found_evt;
}
if (!(fhf->cancel_evt = create_event ()))
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
goto err_close_update_needed_evt;
if (!(fhf->thr_sync_evt = create_event ()))
goto err_close_cancel_evt;
inc_nreaders ();
fhf->me.fh = fhf;
new cygthread (fifo_reader_thread, fhf, "fifo_reader", fhf->thr_sync_evt);
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (writer)
inc_nwriters ();
return 0;
err_close_cancel_evt:
NtClose (fhf->cancel_evt);
err_close_update_needed_evt:
NtClose (fhf->update_needed_evt);
err_close_owner_found_evt:
NtClose (fhf->owner_found_evt);
err_close_owner_needed_evt:
NtClose (fhf->owner_needed_evt);
err_close_shared_fc_handler:
NtUnmapViewOfSection (GetCurrentProcess (), fhf->shared_fc_handler);
err_close_shared_fc_hdl:
NtClose (fhf->shared_fc_hdl);
err_close_shmem:
NtUnmapViewOfSection (GetCurrentProcess (), fhf->shmem);
err_close_shmem_handle:
NtClose (fhf->shmem_handle);
err_close_writer_opening:
NtClose (fhf->writer_opening);
err_close_write_ready:
NtClose (fhf->write_ready);
err_close_read_ready:
NtClose (fhf->read_ready);
err:
return -1;
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
}
void
fhandler_fifo::fixup_after_fork (HANDLE parent)
{
fhandler_base::fixup_after_fork (parent);
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
fork_fixup (parent, read_ready, "read_ready");
fork_fixup (parent, write_ready, "write_ready");
fork_fixup (parent, writer_opening, "writer_opening");
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
fork_fixup (parent, shmem_handle, "shmem_handle");
if (reopen_shmem () < 0)
api_fatal ("Can't reopen shared memory during fork, %E");
if (reader)
{
/* Make sure the child starts unlocked. */
fifo_client_unlock ();
fork_fixup (parent, shared_fc_hdl, "shared_fc_hdl");
if (reopen_shared_fc_handler () < 0)
api_fatal ("Can't reopen shared fc_handler memory during fork, %E");
fork_fixup (parent, owner_needed_evt, "owner_needed_evt");
fork_fixup (parent, owner_found_evt, "owner_found_evt");
fork_fixup (parent, update_needed_evt, "update_needed_evt");
if (close_on_exec ())
/* Prevent a later attempt to close the non-inherited
pipe-instance handles copied from the parent. */
nhandlers = 0;
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");
inc_nreaders ();
me.winpid = GetCurrentProcessId ();
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (writer)
inc_nwriters ();
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
}
void
fhandler_fifo::fixup_after_exec ()
{
fhandler_base::fixup_after_exec ();
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (close_on_exec ())
return;
if (reopen_shmem () < 0)
api_fatal ("Can't reopen shared memory during exec, %E");
if (reader)
{
/* Make sure the child starts unlocked. */
fifo_client_unlock ();
if (reopen_shared_fc_handler () < 0)
api_fatal ("Can't reopen shared fc_handler memory during exec, %E");
fc_handler = NULL;
nhandlers = shandlers = 0;
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");
/* At this moment we're a new reader. The count will be
decremented when the parent closes. */
inc_nreaders ();
me.winpid = GetCurrentProcessId ();
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
}
Cygwin: FIFO: keep a writer count in shared memory When a reader opens, it needs to block if there are no writers open (unless is is opened with O_NONBLOCK). This is easy for the first reader to test, since it can just wait for a writer to signal that it is open (via the write_ready event). But when a second reader wants to open, all writers might have closed. To check this, use a new '_nwriters' member of struct fifo_shmem_t, which keeps track of the number of open writers. This should be more reliable than the previous method. Add nwriters_lock to control access to shmem->_nwriters, and remove reader_opening_lock, which is no longer needed. Previously only readers had access to the shared memory, but now writers access it too so that they can increment _nwriters during open/dup/fork/exec and decrement it during close. Add an optional 'only_open' argument to create_shmem for use by writers, which only open the shared memory rather than first trying to create it. Since writers don't need to access the shared memory until they have successfully connected to a pipe instance, they can safely assume that a reader has already created the shared memory. For debugging purposes, change create_shmem to return 1 instead of 0 when a reader successfully opens the shared memory after finding that it had already been created. Remove check_write_ready_evt, write_ready_ok_evt, and check_write_ready(), which are no longer needed. When opening a writer and looping to try to get a connection, recheck read_ready at the top of the loop since the number of readers might have changed. To slightly speed up the process of opening the first reader, take ownership immediately rather than waiting for the fifo_reader_thread to handle it.
2020-07-12 02:05:23 +08:00
if (writer)
inc_nwriters ();
}
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
void
fhandler_fifo::set_close_on_exec (bool val)
{
fhandler_base::set_close_on_exec (val);
* fhandler.h (fhandler_pipe::create_selectable): Remove optional argument, take an options argument for CreateNamedPipe/CreateFile. Change handle arguments to expect pointers. (fhandler_fifo::fifo_state): Delete. (fhandler_fifo::dummy_client): Ditto. (fhandler_fifo::open_nonserver): Ditto. (fhandler_fifo::wait_state): Ditto. (fhandler_fifo::raw_write): Ditto. (fhandler_fifo::read_ready): New field. (fhandler_fifo::write_ready): Ditto. (fhandler_fifo::wait): Modify argument. (fhandler_fifo::fifo_name): Add a new argument. (fhandler_fifo::fixup_after_fork): New function. * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Remove initialization of expunged elements. Initialize new handles to NULL. (fhandler_fifo::open_nonserver): Delete. (fnevent): New macro for creating a named event. (fnpipe): New macro for creating a unique named pipe name. (create_pipe): New macro for simplification of named pipe creation. (fhandler_fifo::fifo_name): Use new argument when creating a shared name. (fhandler_fifo::open): Rewrite. Use events to synchronize. (pure_debug_printf): New macro, active only when DEBUGGING. (fhandler_fifo::wait): Rewrite to wait for new fifo events which are supplied as a parameter. (fhandler_fifo::raw_read): Rewrite to use handle mechanism to detect client-side disconnect. (fhandler_fifo::raw_write): Delete. (fhandler_fifo::close): Remove accommodations for expunged fields. Close event handles. (fhandler_fifo::dup): Remove accommodations for expunged fields. Duplicate event handles. (fhandler_fifo::fixup_after_fork): New function. Perform fixups on event handles. (fhandler_fifo::set_close_on_exec): Remove accommodations for expunged fields. Set inheritance for new handle fields. * miscfuncs.cc (CreatePipeOverlapped): Accommodate changes in fhandler_pipe::create_selectable. * tty.cc (tty::not_allocated): Ditto. * pipe.cc (fhandler_pipe::create): Ditto. (fhandler_pipe::create_selectable): Accept an extra open_mode argument. Pass arguments by reference and allow opening one end of the pipe at a time. * sys/strace.h (debug_only_printf): Define new macro which calls debug_printf only when DEBUGGING is defined.
2011-10-30 12:50:36 +08:00
set_no_inheritance (read_ready, val);
set_no_inheritance (write_ready, val);
set_no_inheritance (writer_opening, val);
if (reader)
{
set_no_inheritance (owner_needed_evt, val);
set_no_inheritance (owner_found_evt, val);
set_no_inheritance (update_needed_evt, val);
fifo_client_lock ();
for (int i = 0; i < nhandlers; i++)
set_no_inheritance (fc_handler[i].h, val);
fifo_client_unlock ();
}
* sigproc.h (wait_for_sigthread): Eliminate parameter. * sigproc.cc (wait_for_sigthread): Ditto. Don't synchronize with wait_sig after receiving an event that it is ready to go. (init_sig_pipe): New function. (wait_sig): Call init_sig_pipe to create pipes for communicating signals to this process. Don't send sigCONT signal when initializing. * fork.cc (frok::child): Accommodate wait_for_sigpipe parameter change. * fhandler.h (fhandler_*::write): Make ssize_t/__stdcall. (fhandler_*::write_overlapped): Ditto. (fhandler_*::raw_write): Ditto. (fhandler_*::readv): Ditto. (fhandler_*::writev): Ditto. (fhandler_*::raw_read): Make __stdcall. * fhandler: Accommodate changes to read/write functions throughout. * fhandler_clipboard.cc: Ditto. * fhandler_console.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_fifo.cc: Ditto. * fhandler_mailslot.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_tty.cc: Ditto. * fhandler_virtual.cc: Ditto. * fhandler_windows.cc: Ditto. * fhandler_zero.cc: Ditto. * syscalls.cc (readv): Use ssize_t as temp variable. * fhandler.cc (fhandler_base::read): Coerce returned len to signed or it will never be treated as < 0. (fhandler_base::wait_overlapped): Minimize calls to GetLastError. Remove duplicate debugging test. Fix error return. * fhandler.h (fhandler_fifo::fifo_name): Declare new function. (fhandler_fifo::close): Ditto. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto. * fhandler.cc (fhandler_fifo::fifo_name): Define new function. (FIFO_BUF_SIZE): New define. (cnp): Ditto. (fhandler_fifo::open): Rework. Use cnp to open named pipe. Always open write side as a client. Open dummy client when writing and can't connect. (wait): Rework. Implement fifo_wait_for_next_client. Handle signals during connect better. Add new fifo_wait_for_server code which polls (sigh) waiting for server. (fhandler_fifo::raw_read): Handle transition states when one client closes and another is available. (fhandler_fifo::close): Define. (fhandler_fifo::dup): Ditto. (fhandler_fifo::close_on_exec): Ditto.
2009-07-25 04:54:33 +08:00
}