* 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

@ -1,3 +1,52 @@
2011-10-30 Christopher Faylor <me.cygwin2011@cgf.cx>
* 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-28 Christopher Faylor <me.cygwin2011@cgf.cx> 2011-10-28 Christopher Faylor <me.cygwin2011@cgf.cx>
* exceptions.cc (sigpacket::process): Avoid a potential deadlock when * exceptions.cc (sigpacket::process): Avoid a potential deadlock when

View File

@ -275,8 +275,8 @@ retry:
/* Cover function to WriteFile to provide Posix interface and semantics /* Cover function to WriteFile to provide Posix interface and semantics
(as much as possible). */ (as much as possible). */
static LARGE_INTEGER off_current = { QuadPart:FILE_USE_FILE_POINTER_POSITION }; static NO_COPY LARGE_INTEGER off_current = { QuadPart:FILE_USE_FILE_POINTER_POSITION };
static LARGE_INTEGER off_append = { QuadPart:FILE_WRITE_TO_END_OF_FILE }; static NO_COPY LARGE_INTEGER off_append = { QuadPart:FILE_WRITE_TO_END_OF_FILE };
ssize_t __stdcall ssize_t __stdcall
fhandler_base::raw_write (const void *ptr, size_t len) fhandler_base::raw_write (const void *ptr, size_t len)
@ -1914,7 +1914,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
} }
else if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE) else if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE)
{ {
debug_printf ("EOF"); debug_printf ("EOF, %E");
*bytes = 0; *bytes = 0;
res = overlapped_success; res = overlapped_success;
if (writing && err == ERROR_BROKEN_PIPE) if (writing && err == ERROR_BROKEN_PIPE)

View File

@ -129,16 +129,16 @@ class fhandler_base
struct status_flags struct status_flags
{ {
unsigned rbinary : 1; /* binary read mode */ unsigned rbinary : 1; /* binary read mode */
unsigned rbinset : 1; /* binary read mode explicitly set */ unsigned rbinset : 1; /* binary read mode explicitly set */
unsigned wbinary : 1; /* binary write mode */ unsigned wbinary : 1; /* binary write mode */
unsigned wbinset : 1; /* binary write mode explicitly set */ unsigned wbinset : 1; /* binary write mode explicitly set */
unsigned nohandle : 1; /* No handle associated with fhandler. */ unsigned nohandle : 1; /* No handle associated with fhandler. */
unsigned did_lseek : 1; /* set when lseek is called as a flag that unsigned did_lseek : 1; /* set when lseek is called as a flag that
_write should check if we've moved _write should check if we've moved
beyond EOF, zero filling or making beyond EOF, zero filling or making
file sparse if so. */ file sparse if so. */
unsigned query_open : 3; /* open file without requesting either unsigned query_open : 3; /* open file without requesting either
read or write access */ read or write access */
unsigned close_on_exec : 1; /* close-on-exec */ unsigned close_on_exec : 1; /* close-on-exec */
unsigned need_fork_fixup : 1; /* Set if need to fixup after fork. */ unsigned need_fork_fixup : 1; /* Set if need to fixup after fork. */
@ -437,8 +437,8 @@ public:
virtual fhandler_base *clone () virtual fhandler_base *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_base)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_base));
fhandler_base *fh = new (ptr) fhandler_base (ptr); fhandler_base *fh = new (ptr) fhandler_base (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -511,12 +511,12 @@ class fhandler_socket: public fhandler_base
char *peer_sun_path; char *peer_sun_path;
struct status_flags struct status_flags
{ {
unsigned async_io : 1; /* async I/O */ unsigned async_io : 1; /* async I/O */
unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */ unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */
unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */ unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */
unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */ unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */
unsigned listener : 1; /* listen called */ unsigned listener : 1; /* listen called */
unsigned connect_state : 2; unsigned connect_state : 2;
public: public:
status_flags () : status_flags () :
async_io (0), saw_shutdown_read (0), saw_shutdown_write (0), async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
@ -604,8 +604,8 @@ class fhandler_socket: public fhandler_base
fhandler_socket *clone () fhandler_socket *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_socket)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_socket));
fhandler_socket *fh = new (ptr) fhandler_socket (ptr); fhandler_socket *fh = new (ptr) fhandler_socket (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -658,8 +658,8 @@ public:
virtual fhandler_base_overlapped *clone () virtual fhandler_base_overlapped *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_base_overlapped)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_base_overlapped));
fhandler_base_overlapped *fh = new (ptr) fhandler_base_overlapped (ptr); fhandler_base_overlapped *fh = new (ptr) fhandler_base_overlapped (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -690,9 +690,8 @@ public:
int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3))); int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3)));
int init (HANDLE, DWORD, mode_t); int init (HANDLE, DWORD, mode_t);
static int create (fhandler_pipe *[2], unsigned, int); static int create (fhandler_pipe *[2], unsigned, int);
static int create_selectable (LPSECURITY_ATTRIBUTES, HANDLE&, HANDLE&, DWORD, const char * = NULL); static int create_selectable (LPSECURITY_ATTRIBUTES, HANDLE *, HANDLE *, DWORD,
friend class fhandler_fifo; const char *, DWORD);
fhandler_pipe (void *) {} fhandler_pipe (void *) {}
void copyto (fhandler_base *x) void copyto (fhandler_base *x)
@ -704,8 +703,8 @@ public:
fhandler_pipe *clone () fhandler_pipe *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pipe)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pipe));
fhandler_pipe *fh = new (ptr) fhandler_pipe (ptr); fhandler_pipe *fh = new (ptr) fhandler_pipe (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -713,31 +712,19 @@ public:
class fhandler_fifo: public fhandler_base_overlapped class fhandler_fifo: public fhandler_base_overlapped
{ {
enum fifo_state HANDLE read_ready;
{ HANDLE write_ready;
fifo_unknown, bool wait (HANDLE) __attribute__ ((regparm (2)));
fifo_wait_for_client, char *fifo_name (char *, const char *) __attribute__ ((regparm (2)));
fifo_wait_for_server,
fifo_wait_for_next_client,
fifo_eof,
fifo_error,
fifo_eintr,
fifo_ok
};
fifo_state wait_state;
HANDLE dummy_client;
HANDLE open_nonserver (const char *, unsigned, LPSECURITY_ATTRIBUTES);
bool wait (bool) __attribute__ ((regparm (1)));
char *fifo_name (char *) __attribute__ ((regparm (2)));
public: public:
fhandler_fifo (); fhandler_fifo ();
void __stdcall raw_read (void *, size_t&) __attribute__ ((regparm (3)));
ssize_t __stdcall raw_write (const void *, size_t) __attribute__ ((regparm (3)));
int open (int, mode_t); int open (int, mode_t);
int close (); int close ();
int dup (fhandler_base *child, int); int dup (fhandler_base *child, int);
bool isfifo () const { return true; } bool isfifo () const { return true; }
void set_close_on_exec (bool val); void set_close_on_exec (bool val);
void __stdcall raw_read (void *ptr, size_t& ulen) __attribute__ ((regparm (3)));
void fixup_after_fork (HANDLE);
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
select_record *select_read (select_stuff *); select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *); select_record *select_write (select_stuff *);
@ -754,8 +741,8 @@ public:
fhandler_fifo *clone () fhandler_fifo *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_fifo)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_fifo));
fhandler_fifo *fh = new (ptr) fhandler_fifo (ptr); fhandler_fifo *fh = new (ptr) fhandler_fifo (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -783,8 +770,8 @@ class fhandler_mailslot : public fhandler_base_overlapped
fhandler_mailslot *clone () fhandler_mailslot *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_mailslot)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_mailslot));
fhandler_mailslot *fh = new (ptr) fhandler_mailslot (ptr); fhandler_mailslot *fh = new (ptr) fhandler_mailslot (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -832,8 +819,8 @@ class fhandler_dev_raw: public fhandler_base
fhandler_dev_raw *clone () fhandler_dev_raw *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_raw)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_raw));
fhandler_dev_raw *fh = new (ptr) fhandler_dev_raw (ptr); fhandler_dev_raw *fh = new (ptr) fhandler_dev_raw (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -892,8 +879,8 @@ class fhandler_dev_floppy: public fhandler_dev_raw
fhandler_dev_floppy *clone () fhandler_dev_floppy *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_floppy)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_floppy));
fhandler_dev_floppy *fh = new (ptr) fhandler_dev_floppy (ptr); fhandler_dev_floppy *fh = new (ptr) fhandler_dev_floppy (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -940,8 +927,8 @@ class fhandler_dev_tape: public fhandler_dev_raw
fhandler_dev_tape *clone () fhandler_dev_tape *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_tape)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_tape));
fhandler_dev_tape *fh = new (ptr) fhandler_dev_tape (ptr); fhandler_dev_tape *fh = new (ptr) fhandler_dev_tape (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1006,8 +993,8 @@ class fhandler_disk_file: public fhandler_base
fhandler_disk_file *clone () fhandler_disk_file *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_disk_file)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_disk_file));
fhandler_disk_file *fh = new (ptr) fhandler_disk_file (ptr); fhandler_disk_file *fh = new (ptr) fhandler_disk_file (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1044,8 +1031,8 @@ class fhandler_cygdrive: public fhandler_disk_file
fhandler_cygdrive *clone () fhandler_cygdrive *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_cygdrive)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_cygdrive));
fhandler_cygdrive *fh = new (ptr) fhandler_cygdrive (ptr); fhandler_cygdrive *fh = new (ptr) fhandler_cygdrive (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1108,8 +1095,8 @@ class fhandler_serial: public fhandler_base
fhandler_serial *clone () fhandler_serial *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_serial)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_serial));
fhandler_serial *fh = new (ptr) fhandler_serial (ptr); fhandler_serial *fh = new (ptr) fhandler_serial (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1166,8 +1153,8 @@ class fhandler_termios: public fhandler_base
virtual fhandler_termios *clone () virtual fhandler_termios *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_termios)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_termios));
fhandler_termios *fh = new (ptr) fhandler_termios (ptr); fhandler_termios *fh = new (ptr) fhandler_termios (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1365,8 +1352,8 @@ private:
fhandler_console *clone () fhandler_console *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_console)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_console));
fhandler_console *fh = new (ptr) fhandler_console (ptr); fhandler_console *fh = new (ptr) fhandler_console (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1408,8 +1395,8 @@ class fhandler_pty_common: public fhandler_termios
virtual fhandler_pty_common *clone () virtual fhandler_pty_common *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_common)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_common));
fhandler_pty_common *fh = new (ptr) fhandler_pty_common (ptr); fhandler_pty_common *fh = new (ptr) fhandler_pty_common (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1462,8 +1449,8 @@ class fhandler_pty_slave: public fhandler_pty_common
fhandler_pty_slave *clone () fhandler_pty_slave *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_slave)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_slave));
fhandler_pty_slave *fh = new (ptr) fhandler_pty_slave (ptr); fhandler_pty_slave *fh = new (ptr) fhandler_pty_slave (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1520,8 +1507,8 @@ public:
fhandler_pty_master *clone () fhandler_pty_master *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_master)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_pty_master));
fhandler_pty_master *fh = new (ptr) fhandler_pty_master (ptr); fhandler_pty_master *fh = new (ptr) fhandler_pty_master (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1547,8 +1534,8 @@ class fhandler_dev_null: public fhandler_base
fhandler_dev_null *clone () fhandler_dev_null *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_null)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_null));
fhandler_dev_null *fh = new (ptr) fhandler_dev_null (ptr); fhandler_dev_null *fh = new (ptr) fhandler_dev_null (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1582,8 +1569,8 @@ class fhandler_dev_zero: public fhandler_base
fhandler_dev_zero *clone () fhandler_dev_zero *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_zero)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_zero));
fhandler_dev_zero *fh = new (ptr) fhandler_dev_zero (ptr); fhandler_dev_zero *fh = new (ptr) fhandler_dev_zero (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1620,8 +1607,8 @@ class fhandler_dev_random: public fhandler_base
fhandler_dev_random *clone () fhandler_dev_random *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_random)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_random));
fhandler_dev_random *fh = new (ptr) fhandler_dev_random (ptr); fhandler_dev_random *fh = new (ptr) fhandler_dev_random (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1660,8 +1647,8 @@ class fhandler_dev_mem: public fhandler_base
fhandler_dev_mem *clone () fhandler_dev_mem *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_mem)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_mem));
fhandler_dev_mem *fh = new (ptr) fhandler_dev_mem (ptr); fhandler_dev_mem *fh = new (ptr) fhandler_dev_mem (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1696,8 +1683,8 @@ class fhandler_dev_clipboard: public fhandler_base
fhandler_dev_clipboard *clone () fhandler_dev_clipboard *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_clipboard)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_clipboard));
fhandler_dev_clipboard *fh = new (ptr) fhandler_dev_clipboard (ptr); fhandler_dev_clipboard *fh = new (ptr) fhandler_dev_clipboard (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1735,8 +1722,8 @@ class fhandler_windows: public fhandler_base
fhandler_windows *clone () fhandler_windows *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_windows)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_windows));
fhandler_windows *fh = new (ptr) fhandler_windows (ptr); fhandler_windows *fh = new (ptr) fhandler_windows (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1782,8 +1769,8 @@ class fhandler_dev_dsp: public fhandler_base
fhandler_dev_dsp *clone () fhandler_dev_dsp *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_dsp)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_dev_dsp));
fhandler_dev_dsp *fh = new (ptr) fhandler_dev_dsp (ptr); fhandler_dev_dsp *fh = new (ptr) fhandler_dev_dsp (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1833,8 +1820,8 @@ class fhandler_virtual : public fhandler_base
virtual fhandler_virtual *clone () virtual fhandler_virtual *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_virtual)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_virtual));
fhandler_virtual *fh = new (ptr) fhandler_virtual (ptr); fhandler_virtual *fh = new (ptr) fhandler_virtual (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1865,8 +1852,8 @@ class fhandler_proc: public fhandler_virtual
virtual fhandler_proc *clone () virtual fhandler_proc *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_proc)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_proc));
fhandler_proc *fh = new (ptr) fhandler_proc (ptr); fhandler_proc *fh = new (ptr) fhandler_proc (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1901,8 +1888,8 @@ class fhandler_procsys: public fhandler_virtual
fhandler_procsys *clone () fhandler_procsys *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procsys)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procsys));
fhandler_procsys *fh = new (ptr) fhandler_procsys (ptr); fhandler_procsys *fh = new (ptr) fhandler_procsys (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1930,8 +1917,8 @@ class fhandler_procsysvipc: public fhandler_proc
fhandler_procsysvipc *clone () fhandler_procsysvipc *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procsysvipc)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procsysvipc));
fhandler_procsysvipc *fh = new (ptr) fhandler_procsysvipc (ptr); fhandler_procsysvipc *fh = new (ptr) fhandler_procsysvipc (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -1960,8 +1947,8 @@ class fhandler_netdrive: public fhandler_virtual
fhandler_netdrive *clone () fhandler_netdrive *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_netdrive)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_netdrive));
fhandler_netdrive *fh = new (ptr) fhandler_netdrive (ptr); fhandler_netdrive *fh = new (ptr) fhandler_netdrive (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -2000,8 +1987,8 @@ class fhandler_registry: public fhandler_proc
fhandler_registry *clone () fhandler_registry *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_registry)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_registry));
fhandler_registry *fh = new (ptr) fhandler_registry (ptr); fhandler_registry *fh = new (ptr) fhandler_registry (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -2032,8 +2019,8 @@ class fhandler_process: public fhandler_proc
fhandler_process *clone () fhandler_process *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_process)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_process));
fhandler_process *fh = new (ptr) fhandler_process (ptr); fhandler_process *fh = new (ptr) fhandler_process (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }
@ -2061,8 +2048,8 @@ class fhandler_procnet: public fhandler_proc
fhandler_procnet *clone () fhandler_procnet *clone ()
{ {
void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procnet)); void *ptr = (void *) ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_procnet));
fhandler_procnet *fh = new (ptr) fhandler_procnet (ptr); fhandler_procnet *fh = new (ptr) fhandler_procnet (ptr);
copyto (fh); copyto (fh);
return fh; return fh;
} }

View File

@ -24,52 +24,27 @@
#include "ntdll.h" #include "ntdll.h"
fhandler_fifo::fhandler_fifo (): fhandler_fifo::fhandler_fifo ():
fhandler_base_overlapped (), wait_state (fifo_unknown), dummy_client (NULL) fhandler_base_overlapped (),
read_ready (NULL), write_ready (NULL)
{ {
max_atomic_write = DEFAULT_PIPEBUFSIZE; max_atomic_write = DEFAULT_PIPEBUFSIZE;
need_fork_fixup (true); need_fork_fixup (true);
} }
HANDLE #define fnevent(w) fifo_name (npbuf, w "-event")
fhandler_fifo::open_nonserver (const char *npname, unsigned low_flags, #define fnpipe() fifo_name (npbuf, "fifo")
LPSECURITY_ATTRIBUTES sa_buf) #define create_pipe(r, w) \
{ fhandler_pipe::create_selectable (sa_buf, (r), (w), 0, fnpipe (), open_mode)
DWORD mode = 0;
if (low_flags == O_RDONLY)
mode = GENERIC_READ;
else if (low_flags == O_WRONLY)
mode = GENERIC_WRITE;
else
mode = GENERIC_READ | GENERIC_WRITE;
while (1)
{
HANDLE h = CreateFile (npname, mode, 0, sa_buf, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if (h != INVALID_HANDLE_VALUE || GetLastError () != ERROR_PIPE_NOT_CONNECTED)
return h;
if (IsEventSignalled (signal_arrived))
{
set_errno (EINTR);
return NULL;
}
}
}
char * char *
fhandler_fifo::fifo_name (char *buf) fhandler_fifo::fifo_name (char *buf, const char *what)
{ {
/* Generate a semi-unique name to associate with this fifo. */ /* Generate a semi-unique name to associate with this fifo. */
__small_sprintf (buf, "\\\\.\\pipe\\__cygfifo__%S_%08x_%016X", __small_sprintf (buf, "%s.%08x.%016X", what, get_dev (),
&installation_key, get_dev (), get_ino ()); get_ino ());
return buf; return buf;
} }
#define FIFO_PIPE_MODE (PIPE_TYPE_BYTE | PIPE_READMODE_BYTE)
#define FIFO_BUF_SIZE 4096
#define cnp(m, s) CreateNamedPipe(npname, (m), FIFO_PIPE_MODE, \
PIPE_UNLIMITED_INSTANCES, (s), (s), \
NMPWAIT_WAIT_FOREVER, sa_buf)
inline PSECURITY_ATTRIBUTES inline PSECURITY_ATTRIBUTES
sec_user_cloexec (bool cloexec, PSECURITY_ATTRIBUTES sa, PSID sid) sec_user_cloexec (bool cloexec, PSECURITY_ATTRIBUTES sa, PSID sid)
{ {
@ -79,207 +54,242 @@ sec_user_cloexec (bool cloexec, PSECURITY_ATTRIBUTES sa, PSID sid)
int int
fhandler_fifo::open (int flags, mode_t) fhandler_fifo::open (int flags, mode_t)
{ {
int res = 1; enum
char npname[MAX_PATH]; {
success,
error_errno_set,
error_set_errno
} res;
bool reader, writer;
DWORD open_mode = FILE_FLAG_OVERLAPPED;
fifo_name (npname); /* Determine what we're doing with this fhandler: reading, writing, both */
unsigned low_flags = flags & O_ACCMODE; switch (flags & O_ACCMODE)
DWORD mode = 0; {
if (low_flags == O_WRONLY) case O_RDONLY:
mode = PIPE_ACCESS_OUTBOUND; reader = true;
else if (low_flags == O_RDONLY || low_flags == O_RDWR) writer = false;
mode = PIPE_ACCESS_DUPLEX; break;
case O_WRONLY:
writer = true;
reader = false;
break;
case O_RDWR:
reader = true;
writer = true;
open_mode |= PIPE_ACCESS_DUPLEX;
break;
default:
set_errno (EINVAL);
res = error_errno_set;
goto out;
}
set_flags (flags);
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];
/* Create control events for this named pipe */
if (!(read_ready = CreateEvent (sa_buf, true, false, fnevent ("r"))))
{
debug_printf ("CreatEvent for %s failed, %E", npbuf);
res = error_set_errno;
goto out;
}
if (!(write_ready = CreateEvent (sa_buf, true, false, fnevent ("w"))))
{
debug_printf ("CreatEvent for %s failed, %E", npbuf);
res = error_set_errno;
goto out;
}
/* If we're reading, create the pipe, signal that we're ready and wait for
a writer.
FIXME: Probably need to special case O_RDWR case. */
if (!reader)
/* We are not a reader */;
else if (create_pipe (&get_io_handle (), NULL))
{
debug_printf ("create of reader failed");
res = error_set_errno;
goto out;
}
else if (!SetEvent (read_ready))
{
debug_printf ("SetEvent for read_ready failed, %E");
res = error_set_errno;
goto out;
}
else if (!writer && !wait (write_ready))
{
debug_printf ("wait for write_ready failed, %E");
res = error_errno_set;
goto out;
}
/* If we're writing, it's a little tricky since it is possible that
we're attempting to open the other end of a pipe which is already
connected. In that case, we detect ERROR_PIPE_BUSY, reset the
read_ready event and wait for the reader to allow us to connect
by signalling read_ready.
Once the pipe has been set up, we signal write_ready. */
if (writer)
{
int err;
while (1)
if (!wait (read_ready))
{
res = error_errno_set;
goto out;
}
else if ((err = create_pipe (NULL, &get_io_handle ())) == 0)
break;
else if (err == ERROR_PIPE_BUSY)
{
debug_only_printf ("pipe busy");
ResetEvent (read_ready);
}
else
{
debug_printf ("create of writer failed");
res = error_set_errno;
goto out;
}
if (!SetEvent (write_ready))
{
debug_printf ("SetEvent for write_ready failed, %E");
res = error_set_errno;
goto out;
}
}
/* If setup_overlapped() succeeds (and why wouldn't it?) we are all set. */
if (setup_overlapped () == 0)
res = success;
else else
{ {
set_errno (EINVAL); debug_printf ("setup_overlapped failed, %E");
res = 0; res = error_set_errno;
} }
if (res) out:
if (res == error_set_errno)
__seterrno ();
if (res != success)
{ {
char char_sa_buf[1024]; if (read_ready)
LPSECURITY_ATTRIBUTES sa_buf =
sec_user_cloexec (flags & O_CLOEXEC, (PSECURITY_ATTRIBUTES) char_sa_buf,
cygheap->user.sid());
bool do_seterrno = true;
HANDLE h;
bool nonblocking_write = !!((flags & (O_WRONLY | O_NONBLOCK)) == (O_WRONLY | O_NONBLOCK));
wait_state = fifo_unknown;
if (mode != PIPE_ACCESS_OUTBOUND)
{ {
h = cnp (mode | FILE_FLAG_OVERLAPPED, FIFO_BUF_SIZE); CloseHandle (read_ready);
wait_state = fifo_wait_for_client; read_ready = NULL;
} }
else if (write_ready)
{ {
h = open_nonserver (npname, low_flags, sa_buf); CloseHandle (write_ready);
if (h != INVALID_HANDLE_VALUE) write_ready = NULL;
wait_state = fifo_ok;
else if (nonblocking_write)
{
set_errno (ENXIO);
do_seterrno = false;
}
else if ((h = cnp (PIPE_ACCESS_DUPLEX, 1)) != INVALID_HANDLE_VALUE)
{
if ((dummy_client = open_nonserver (npname, low_flags, sa_buf))
!= INVALID_HANDLE_VALUE)
{
wait_state = fifo_wait_for_server;
ProtectHandle (dummy_client);
}
else
{
DWORD saveerr = GetLastError ();
CloseHandle (h);
h = INVALID_HANDLE_VALUE;
SetLastError (saveerr);
}
}
}
if (h == INVALID_HANDLE_VALUE)
{
if (do_seterrno)
__seterrno ();
res = 0;
}
else if (setup_overlapped ())
{
CloseHandle (h);
__seterrno ();
res = 0;
}
else
{
set_io_handle (h);
set_flags (flags);
res = 1;
} }
if (get_io_handle ())
CloseHandle (get_io_handle ());
} }
debug_printf ("res %d", res);
debug_printf ("returning %d, errno %d", res, get_errno ()); return res == success;
return res;
} }
bool bool
fhandler_fifo::wait (bool iswrite) fhandler_fifo::wait (HANDLE h)
{ {
DWORD ninstances; #ifdef DEBUGGING
switch (wait_state) const char *what;
if (h == read_ready)
what = "reader";
else if (h == write_ready)
what = "writer";
else
what = "overlapped event";
#endif
HANDLE w4[3] = {h, signal_arrived, pthread::get_cancel_event ()};
/* 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 (WaitForMultipleObjects (3, w4, false, wait))
{ {
case fifo_wait_for_next_client: case WAIT_OBJECT_0:
DisconnectNamedPipe (get_handle ()); debug_only_printf ("successfully waited for %s", what);
if (!GetNamedPipeHandleState (get_handle (), NULL, &ninstances, NULL, NULL, NULL, 0)) return true;
case WAIT_TIMEOUT:
if (h == write_ready)
{ {
__seterrno (); debug_only_printf ("wait timed out waiting for write but will still open reader since non-blocking mode");
wait_state = fifo_error; return true;
}
else
{
set_errno (ENXIO);
return false; return false;
} }
if (ninstances <= 1)
{
wait_state = fifo_eof;
return false;
}
case fifo_wait_for_client:
{
DWORD dummy_bytes;
while (1)
{
int res = ConnectNamedPipe (get_handle (), get_overlapped ());
if (GetLastError () != ERROR_NO_DATA && GetLastError () != ERROR_PIPE_CONNECTED)
{
res = wait_overlapped (res, iswrite, &dummy_bytes, false);
if (!res)
{
if (get_errno () != EINTR)
wait_state = fifo_error;
else if (!_my_tls.call_signal_handler ())
wait_state = fifo_eintr;
else
continue;
return false;
}
}
wait_state = fifo_ok;
break;
}
}
break; break;
case fifo_wait_for_server: case WAIT_OBJECT_0 + 1:
char npname[MAX_PATH]; debug_only_printf ("interrupted by signal while waiting for %s", what);
fifo_name (npname); set_errno (EINTR);
char char_sa_buf[1024]; return false;
LPSECURITY_ATTRIBUTES sa_buf; case WAIT_OBJECT_0 + 2:
sa_buf = sec_user_cloexec (close_on_exec (), debug_only_printf ("cancellable interruption while waiting for %s", what);
(PSECURITY_ATTRIBUTES) char_sa_buf, pthread::static_cancel_self (); /* never returns */
cygheap->user.sid()); break;
while (1)
{
if (WaitNamedPipe (npname, 10))
/* connected, maybe */;
else if (GetLastError () != ERROR_SEM_TIMEOUT)
{
__seterrno ();
return false;
}
else if (!IsEventSignalled (signal_arrived))
continue;
else if (_my_tls.call_signal_handler ())
continue;
else
{
set_errno (EINTR);
return false;
}
HANDLE h = open_nonserver (npname, get_flags () & O_ACCMODE, sa_buf);
if (h != INVALID_HANDLE_VALUE)
{
ForceCloseHandle (get_handle ());
ForceCloseHandle (dummy_client);
dummy_client = NULL;
wait_state = fifo_ok;
set_io_handle (h);
break;
}
if (GetLastError () == ERROR_PIPE_LISTENING)
continue;
else
{
__seterrno ();
return false;
}
}
default: default:
break; debug_only_printf ("unknown error while waiting for %s", what);
} __seterrno ();
return true; return false;
}
} }
void __stdcall void __stdcall
fhandler_fifo::raw_read (void *in_ptr, size_t& len) fhandler_fifo::raw_read (void *in_ptr, size_t& len)
{ {
while (wait_state != fifo_eof && wait_state != fifo_error && wait_state != fifo_eintr) size_t orig_len = len;
if (!wait (false)) for (int i = 0; i < 2; i++)
len = (wait_state == fifo_error || wait_state == fifo_eintr) ? (size_t) -1 : 0; {
else fhandler_base_overlapped::raw_read (in_ptr, len);
{ if (len || i || WaitForSingleObject (read_ready, 0) == WAIT_OBJECT_0)
size_t prev_len = len; break;
fhandler_base_overlapped::raw_read (in_ptr, len); /* If we got here, then fhandler_base_overlapped::raw_read returned 0,
if (len) indicating "EOF" and something has set read_ready to zero. That means
break; we should have a client waiting to connect.
wait_state = fifo_wait_for_next_client; FIXME: If the client CTRL-C's the open during this time then this
len = prev_len; could hang indefinitely. Maybe implement a timeout? */
} if (!DisconnectNamedPipe (get_io_handle ()))
if (wait_state == fifo_eintr) {
wait_state = fifo_wait_for_client; debug_printf ("DisconnecttNamedPipe failed, %E");
debug_printf ("returning %d, mode %d, %E\n", len, get_errno ()); goto errno_out;
} }
else if (!ConnectNamedPipe (get_io_handle (), get_overlapped ())
&& GetLastError () != ERROR_IO_PENDING)
{
debug_printf ("ConnectNamedPipe failed, %E");
goto errno_out;
}
else if (!SetEvent (read_ready))
{
debug_printf ("SetEvent (read_ready) failed, %E");
goto errno_out;
}
else if (!wait (get_overlapped_buffer ()->hEvent))
goto errout; /* If wait() fails, errno is set so no need to set it */
len = orig_len; /* Reset since raw_read above set it to zero. */
}
return;
ssize_t __stdcall errno_out:
fhandler_fifo::raw_write (const void *ptr, size_t len) __seterrno ();
{ errout:
return wait (true) ? fhandler_base_overlapped::raw_write (ptr, len) : -1; len = -1;
} }
int __stdcall int __stdcall
@ -293,41 +303,52 @@ fhandler_fifo::fstatvfs (struct statvfs *sfs)
int int
fhandler_fifo::close () fhandler_fifo::close ()
{ {
wait_state = fifo_eof; CloseHandle (read_ready);
if (dummy_client) CloseHandle (write_ready);
{
ForceCloseHandle (dummy_client);
dummy_client = NULL;
}
return fhandler_base::close (); return fhandler_base::close ();
} }
int int
fhandler_fifo::dup (fhandler_base *child, int flags) fhandler_fifo::dup (fhandler_base *child, int flags)
{ {
int res = fhandler_base_overlapped::dup (child, flags); if (fhandler_base_overlapped::dup (child, flags))
fhandler_fifo *fifo_child = (fhandler_fifo *) child;
if (res == 0 && dummy_client)
{ {
bool dres = DuplicateHandle (GetCurrentProcess (), dummy_client, __seterrno ();
GetCurrentProcess (), return -1;
&fifo_child->dummy_client, 0,
TRUE, DUPLICATE_SAME_ACCESS);
if (!dres)
{
fifo_child->dummy_client = NULL;
child->close ();
__seterrno ();
res = -1;
}
} }
return res; fhandler_fifo *fhf = (fhandler_fifo *) child;
if (!DuplicateHandle (GetCurrentProcess (), read_ready,
GetCurrentProcess (), &fhf->read_ready,
0, true, DUPLICATE_SAME_ACCESS))
{
fhf->close ();
__seterrno ();
return -1;
}
if (!DuplicateHandle (GetCurrentProcess (), write_ready,
GetCurrentProcess (), &fhf->write_ready,
0, true, DUPLICATE_SAME_ACCESS))
{
CloseHandle (fhf->read_ready);
fhf->close ();
__seterrno ();
return -1;
}
return 0;
}
void
fhandler_fifo::fixup_after_fork (HANDLE parent)
{
fhandler_base_overlapped::fixup_after_fork (parent);
fork_fixup (parent, read_ready, "read_ready");
fork_fixup (parent, write_ready, "write_ready");
} }
void void
fhandler_fifo::set_close_on_exec (bool val) fhandler_fifo::set_close_on_exec (bool val)
{ {
fhandler_base::set_close_on_exec (val); fhandler_base::set_close_on_exec (val);
if (dummy_client) set_no_inheritance (read_ready, val);
set_no_inheritance (dummy_client, val); set_no_inheritance (write_ready, val);
} }

View File

@ -1624,8 +1624,8 @@ fhandler_pty_master::setup ()
char pipename[sizeof("ptyNNNN-from-master")]; char pipename[sizeof("ptyNNNN-from-master")];
__small_sprintf (pipename, "pty%d-to-master", unit); __small_sprintf (pipename, "pty%d-to-master", unit);
res = fhandler_pipe::create_selectable (&sec_none, get_io_handle (), res = fhandler_pipe::create_selectable (&sec_none, &get_io_handle (),
to_master, 128 * 1024, pipename); &to_master, 128 * 1024, pipename, 0);
if (res) if (res)
{ {
errstr = "output pipe"; errstr = "output pipe";

View File

@ -125,6 +125,11 @@ void strace_printf (unsigned, const char *func, const char *, ...);
})) }))
#endif /*NOSTRACE*/ #endif /*NOSTRACE*/
#ifdef DEBUGGING
#define debug_only_printf(fmt, args...) debug_printf (fmt , ## args)
#else
#define debug_only_printf(fmt, args...) do {} while (0)
#endif
#define debug_printf(fmt, args...) strace_printf_wrap(DEBUG, fmt , ## args) #define debug_printf(fmt, args...) strace_printf_wrap(DEBUG, fmt , ## args)
#define malloc_printf(fmt, args...) strace_printf_wrap1(MALLOC, fmt , ## args) #define malloc_printf(fmt, args...) strace_printf_wrap1(MALLOC, fmt , ## args)
#define minimal_printf(fmt, args...) strace_printf_wrap1(MINIMAL, fmt , ## args) #define minimal_printf(fmt, args...) strace_printf_wrap1(MINIMAL, fmt , ## args)

View File

@ -337,7 +337,8 @@ nice_to_winprio (int &nice)
BOOL WINAPI BOOL WINAPI
CreatePipeOverlapped (PHANDLE hr, PHANDLE hw, LPSECURITY_ATTRIBUTES sa) CreatePipeOverlapped (PHANDLE hr, PHANDLE hw, LPSECURITY_ATTRIBUTES sa)
{ {
int ret = fhandler_pipe::create_selectable (sa, *hr, *hw, 0); int ret = fhandler_pipe::create_selectable (sa, hr, hw, 0, NULL,
FILE_FLAG_OVERLAPPED);
if (ret) if (ret)
SetLastError (ret); SetLastError (ret);
return ret == 0; return ret == 0;

View File

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

View File

@ -159,8 +159,8 @@ tty::not_allocated (HANDLE& r, HANDLE& w)
char pipename[sizeof("ptyNNNN-from-master")]; char pipename[sizeof("ptyNNNN-from-master")];
__small_sprintf (pipename, "pty%d-from-master", get_unit ()); __small_sprintf (pipename, "pty%d-from-master", get_unit ());
/* fhandler_pipe::create_selectable returns 0 when creation succeeds */ /* fhandler_pipe::create_selectable returns 0 when creation succeeds */
return fhandler_pipe::create_selectable (&sec_none, r, w, 128 * 1024, return fhandler_pipe::create_selectable (&sec_none, &r, &w, 128 * 1024,
pipename) == 0; pipename, 0) == 0;
} }
bool bool