* 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:
Christopher Faylor
2011-10-30 04:50:36 +00:00
parent 673a691372
commit cd071d1363
9 changed files with 449 additions and 369 deletions

View File

@ -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)