* 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.
This commit is contained in:
@ -197,11 +197,14 @@ fhandler_pipe::dup (fhandler_base *child, int flags)
|
||||
Note that the return value is either 0 or GetLastError,
|
||||
unlike CreatePipe, which returns a bool for success or failure. */
|
||||
int
|
||||
fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
|
||||
HANDLE& w, DWORD psize, const char *name)
|
||||
fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE *r,
|
||||
HANDLE *w, DWORD psize, const char *name, DWORD open_mode)
|
||||
{
|
||||
/* Default to error. */
|
||||
r = w = INVALID_HANDLE_VALUE;
|
||||
if (r)
|
||||
*r = NULL;
|
||||
if (w)
|
||||
*w = NULL;
|
||||
|
||||
/* Ensure that there is enough pipe buffer space for atomic writes. */
|
||||
if (psize < DEFAULT_PIPEBUFSIZE)
|
||||
@ -210,26 +213,24 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
|
||||
char pipename[MAX_PATH];
|
||||
const size_t len = __small_sprintf (pipename, PIPE_INTRO "%S-",
|
||||
&installation_key);
|
||||
if (name)
|
||||
strcpy (pipename + len, name);
|
||||
|
||||
/* FIXME: Eventually make ttys work with overlapped I/O. */
|
||||
DWORD overlapped = name ? 0 : FILE_FLAG_OVERLAPPED;
|
||||
open_mode |= PIPE_ACCESS_INBOUND;
|
||||
|
||||
/* Retry CreateNamedPipe as long as the pipe name is in use.
|
||||
Retrying will probably never be necessary, but we want
|
||||
to be as robust as possible. */
|
||||
DWORD err;
|
||||
do
|
||||
DWORD err = 0;
|
||||
while (r && !*r)
|
||||
{
|
||||
static volatile ULONG pipe_unique_id;
|
||||
if (!name)
|
||||
__small_sprintf (pipename + len, "pipe-%p-%p", myself->pid,
|
||||
InterlockedIncrement ((LONG *) &pipe_unique_id));
|
||||
else
|
||||
strcpy (pipename + len, name);
|
||||
|
||||
debug_printf ("CreateNamedPipe: name %s, size %lu", pipename, psize);
|
||||
|
||||
err = 0;
|
||||
/* Use CreateNamedPipe instead of CreatePipe, because the latter
|
||||
returns a write handle that does not permit FILE_READ_ATTRIBUTES
|
||||
access, on versions of win32 earlier than WinXP SP2.
|
||||
@ -245,13 +246,14 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
|
||||
definitely required for pty handling since fhandler_pty_master
|
||||
writes to the pipe in chunks, terminated by newline when CANON mode
|
||||
is specified. */
|
||||
r = CreateNamedPipe (pipename, PIPE_ACCESS_INBOUND | overlapped,
|
||||
*r = CreateNamedPipe (pipename, open_mode,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE, 1, psize,
|
||||
psize, NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
|
||||
|
||||
if (r != INVALID_HANDLE_VALUE)
|
||||
if (*r != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
debug_printf ("pipe read handle %p", r);
|
||||
debug_printf ("pipe read handle %p", *r);
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -261,43 +263,58 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
|
||||
case ERROR_PIPE_BUSY:
|
||||
/* The pipe is already open with compatible parameters.
|
||||
Pick a new name and retry. */
|
||||
debug_printf ("pipe busy", name ? ", retrying" : "");
|
||||
debug_printf ("pipe busy", !name ? ", retrying" : "");
|
||||
if (!*name)
|
||||
*r = NULL;
|
||||
break;
|
||||
case ERROR_ACCESS_DENIED:
|
||||
/* The pipe is already open with incompatible parameters.
|
||||
Pick a new name and retry. */
|
||||
debug_printf ("pipe access denied%s", name ? ", retrying" : "");
|
||||
debug_printf ("pipe access denied%s", !name ? ", retrying" : "");
|
||||
if (!*name)
|
||||
*r = NULL;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
err = GetLastError ();
|
||||
debug_printf ("CreatePipe failed, %E");
|
||||
return err;
|
||||
debug_printf ("failed, %E");
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!name);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
debug_printf ("CreateFile: name %s", pipename);
|
||||
|
||||
/* Open the named pipe for writing.
|
||||
Be sure to permit FILE_READ_ATTRIBUTES access. */
|
||||
w = CreateFile (pipename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, sa_ptr,
|
||||
OPEN_EXISTING, overlapped, 0);
|
||||
|
||||
if (!w || w == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* Failure. */
|
||||
DWORD err = GetLastError ();
|
||||
debug_printf ("CreateFile failed, %E");
|
||||
CloseHandle (r);
|
||||
*r = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
debug_printf ("pipe write handle %p", w);
|
||||
if (!w)
|
||||
debug_printf ("pipe write handle NULL");
|
||||
else
|
||||
{
|
||||
debug_printf ("CreateFile: name %s", pipename);
|
||||
|
||||
/* Open the named pipe for writing.
|
||||
Be sure to permit FILE_READ_ATTRIBUTES access. */
|
||||
DWORD access = GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
||||
if ((open_mode & PIPE_ACCESS_DUPLEX) == PIPE_ACCESS_DUPLEX)
|
||||
access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
||||
*w = CreateFile (pipename, access, 0, sa_ptr, OPEN_EXISTING,
|
||||
open_mode & FILE_FLAG_OVERLAPPED, 0);
|
||||
|
||||
if (!*w || *w == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* Failure. */
|
||||
DWORD err = GetLastError ();
|
||||
debug_printf ("CreateFile failed, %E");
|
||||
if (r)
|
||||
CloseHandle (*r);
|
||||
*w = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
debug_printf ("pipe write handle %p", *w);
|
||||
}
|
||||
|
||||
/* Success. */
|
||||
return 0;
|
||||
@ -310,7 +327,7 @@ fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
|
||||
SECURITY_ATTRIBUTES *sa = sec_none_cloexec (mode);
|
||||
int res = -1;
|
||||
|
||||
int ret = create_selectable (sa, r, w, psize);
|
||||
int ret = create_selectable (sa, &r, &w, psize, NULL, FILE_FLAG_OVERLAPPED);
|
||||
if (ret)
|
||||
__seterrno_from_win_error (ret);
|
||||
else if ((fhs[0] = (fhandler_pipe *) build_fh_dev (*piper_dev)) == NULL)
|
||||
|
Reference in New Issue
Block a user