From 43c23d4b822cc23f35c3668272526bebf3630454 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Fri, 24 Jul 2009 20:54:33 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 58 +++++++ winsup/cygwin/fhandler.cc | 31 ++-- winsup/cygwin/fhandler.h | 83 +++++----- winsup/cygwin/fhandler_clipboard.cc | 2 +- winsup/cygwin/fhandler_console.cc | 2 +- winsup/cygwin/fhandler_dsp.cc | 2 +- winsup/cygwin/fhandler_fifo.cc | 235 +++++++++++++++++++++------- winsup/cygwin/fhandler_floppy.cc | 4 +- winsup/cygwin/fhandler_mailslot.cc | 2 +- winsup/cygwin/fhandler_mem.cc | 2 +- winsup/cygwin/fhandler_random.cc | 2 +- winsup/cygwin/fhandler_serial.cc | 4 +- winsup/cygwin/fhandler_tape.cc | 4 +- winsup/cygwin/fhandler_tty.cc | 4 +- winsup/cygwin/fhandler_virtual.cc | 4 +- winsup/cygwin/fhandler_windows.cc | 2 +- winsup/cygwin/fhandler_zero.cc | 2 +- winsup/cygwin/fork.cc | 2 +- winsup/cygwin/sigproc.cc | 35 +++-- winsup/cygwin/sigproc.h | 2 +- winsup/cygwin/syscalls.cc | 2 +- 21 files changed, 341 insertions(+), 143 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 50b183dbe..49cc67e79 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,61 @@ +2009-07-24 Christopher Faylor + + * 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. + +2009-07-24 Christopher Faylor + + * 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-24 Corinna Vinschen * syscalls.cc (internal_setlocale): Fix typo in GBK codepage. diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 9ba286ec0..b8f624e2f 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -209,7 +209,7 @@ fhandler_base::set_flags (int flags, int supplied_bin) /* Cover function to ReadFile to achieve (as much as possible) Posix style semantics and use of errno. */ -void +void __stdcall fhandler_base::raw_read (void *ptr, size_t& ulen) { #define bytes_read ulen @@ -278,7 +278,7 @@ retry: static LARGE_INTEGER off_current = { QuadPart:FILE_USE_FILE_POINTER_POSITION }; static LARGE_INTEGER off_append = { QuadPart:FILE_WRITE_TO_END_OF_FILE }; -int +ssize_t __stdcall fhandler_base::raw_write (const void *ptr, size_t len) { NTSTATUS status; @@ -649,7 +649,7 @@ done: an \n. If last char is an \r, look ahead one more char, if \n then modify \r, if not, remember char. */ -void +void __stdcall fhandler_base::read (void *in_ptr, size_t& len) { char *ptr = (char *) in_ptr; @@ -676,7 +676,7 @@ fhandler_base::read (void *in_ptr, size_t& len) else len = copied_chars; - if (rbinary () || len <= 0) + if (rbinary () || (ssize_t) len <= 0) goto out; /* Scan buffer and turn \r\n into \n */ @@ -739,7 +739,7 @@ out: debug_printf ("returning %d, %s mode", len, rbinary () ? "binary" : "text"); } -int +ssize_t __stdcall fhandler_base::write (const void *ptr, size_t len) { int res; @@ -834,7 +834,7 @@ fhandler_base::write (const void *ptr, size_t len) return res; } -ssize_t +ssize_t __stdcall fhandler_base::readv (const struct iovec *const iov, const int iovcnt, ssize_t tot) { @@ -891,7 +891,7 @@ fhandler_base::readv (const struct iovec *const iov, const int iovcnt, return len; } -ssize_t +ssize_t __stdcall fhandler_base::writev (const struct iovec *const iov, const int iovcnt, ssize_t tot) { @@ -1682,10 +1682,10 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le int res = 0; - DWORD err; + DWORD err = GetLastError (); if (is_nonblocking ()) { - if (inres || GetLastError () == ERROR_IO_PENDING) + if (inres || err == ERROR_IO_PENDING) { if (writing && !inres) *bytes = len; /* This really isn't true but it seems like @@ -1696,17 +1696,10 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le res = 1; err = 0; } - else - { - res = 0; - err = GetLastError (); - } } - else if (inres || ((err = GetLastError ()) == ERROR_IO_PENDING)) + else if (inres || err == ERROR_IO_PENDING) { #ifdef DEBUGGING - if (!get_overlapped ()) - system_printf ("get_overlapped is zero?"); if (!get_overlapped ()->hEvent) system_printf ("hEvent is zero?"); #endif @@ -1749,7 +1742,7 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le debug_printf ("err %u", err); __seterrno_from_win_error (err); *bytes = (DWORD) -1; - res = -1; + res = 0; } else { @@ -1796,7 +1789,7 @@ fhandler_base::read_overlapped (void *ptr, size_t& len) len = (size_t) nbytes; } -int __stdcall +ssize_t __stdcall fhandler_base::write_overlapped (const void *ptr, size_t len) { DWORD nbytes; diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 4995d15b2..382a592cb 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -310,10 +310,10 @@ class fhandler_base virtual void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); virtual void __stdcall read_overlapped (void *ptr, size_t& len) __attribute__ ((regparm (3))); virtual bool __stdcall has_ongoing_io (bool) __attribute__ ((regparm (2))); - virtual int write (const void *ptr, size_t len); - virtual int __stdcall write_overlapped (const void *ptr, size_t len); - virtual ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1); - virtual ssize_t writev (const struct iovec *, int iovcnt, ssize_t tot = -1); + virtual ssize_t __stdcall write (const void *ptr, size_t len); + virtual ssize_t __stdcall write_overlapped (const void *ptr, size_t len); + virtual ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1); + virtual ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1); virtual ssize_t __stdcall pread (void *, size_t, _off64_t) __attribute__ ((regparm (3))); virtual ssize_t __stdcall pwrite (void *, size_t, _off64_t) __attribute__ ((regparm (3))); virtual _off64_t lseek (_off64_t offset, int whence); @@ -349,8 +349,8 @@ class fhandler_base virtual class fhandler_console *is_console () { return 0; } virtual int is_windows () {return 0; } - virtual void raw_read (void *ptr, size_t& ulen); - virtual int raw_write (const void *ptr, size_t ulen); + virtual void __stdcall raw_read (void *ptr, size_t& ulen); + virtual ssize_t __stdcall raw_write (const void *ptr, size_t ulen); virtual OVERLAPPED *get_overlapped () {return NULL;} virtual OVERLAPPED *get_overlapped_buffer () {return NULL;} virtual void set_overlapped (OVERLAPPED *) {} @@ -399,7 +399,7 @@ class fhandler_mailslot : public fhandler_base fhandler_mailslot (); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); int ioctl (unsigned int cmd, void *); select_record *select_read (select_stuff *); }; @@ -499,13 +499,13 @@ class fhandler_socket: public fhandler_base int getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid); int open (int flags, mode_t mode = 0); - ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1); + ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1); inline ssize_t recv_internal (struct _WSAMSG *wsamsg); ssize_t recvfrom (void *ptr, size_t len, int flags, struct sockaddr *from, int *fromlen); ssize_t recvmsg (struct msghdr *msg, int flags); - ssize_t writev (const struct iovec *, int iovcnt, ssize_t tot = -1); + ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1); inline ssize_t send_internal (struct _WSAMSG *wsamsg, int flags); ssize_t sendto (const void *ptr, size_t len, int flags, const struct sockaddr *to, int tolen); @@ -563,8 +563,8 @@ public: select_record *select_write (select_stuff *); select_record *select_except (select_stuff *); char *get_proc_fd_name (char *buf); - void raw_read (void *ptr, size_t& len); - int raw_write (const void *, size_t); + void __stdcall raw_read (void *ptr, size_t& len); + ssize_t __stdcall raw_write (const void *, size_t); int open (int flags, mode_t mode = 0); int dup (fhandler_base *child); int ioctl (unsigned int cmd, void *); @@ -578,25 +578,34 @@ public: friend class fhandler_fifo; }; -enum fifo_state -{ - fifo_unknown, - fifo_wait_for_client, - fifo_wait_for_server, - fifo_ok -}; class fhandler_fifo: public fhandler_base { + enum fifo_state + { + fifo_unknown, + fifo_wait_for_client, + 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); OVERLAPPED io_status; bool wait (bool) __attribute__ ((regparm (1))); + char *fifo_name (char *) __attribute__ ((regparm (2))); public: fhandler_fifo (); - void raw_read (void *, size_t&); - int raw_write (const void *, size_t); + void __stdcall raw_read (void *, size_t&); + ssize_t __stdcall raw_write (const void *, size_t); int open (int, mode_t); + int close (); + int dup (fhandler_base *child); bool isfifo () { return true; } + void set_close_on_exec (bool val); int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); OVERLAPPED *get_overlapped () {return &io_status;} OVERLAPPED *get_overlapped_buffer () {return &io_status;} @@ -662,8 +671,8 @@ class fhandler_dev_floppy: public fhandler_dev_raw int open (int flags, mode_t mode = 0); int dup (fhandler_base *child); - void raw_read (void *ptr, size_t& ulen); - int raw_write (const void *ptr, size_t ulen); + void __stdcall raw_read (void *ptr, size_t& ulen); + ssize_t __stdcall raw_write (const void *ptr, size_t ulen); _off64_t lseek (_off64_t offset, int whence); int ioctl (unsigned int cmd, void *buf); }; @@ -686,8 +695,8 @@ class fhandler_dev_tape: public fhandler_dev_raw virtual int open (int flags, mode_t mode = 0); virtual int close (); - void raw_read (void *ptr, size_t& ulen); - int raw_write (const void *ptr, size_t ulen); + void __stdcall raw_read (void *ptr, size_t& ulen); + ssize_t __stdcall raw_write (const void *ptr, size_t ulen); virtual _off64_t lseek (_off64_t offset, int whence); @@ -780,8 +789,8 @@ class fhandler_serial: public fhandler_base int init (HANDLE h, DWORD a, mode_t flags); void overlapped_setup (); int dup (fhandler_base *child); - void raw_read (void *ptr, size_t& ulen); - int raw_write (const void *ptr, size_t ulen); + void __stdcall raw_read (void *ptr, size_t& ulen); + ssize_t __stdcall raw_write (const void *ptr, size_t ulen); int tcsendbreak (int); int tcdrain (); int tcflow (int); @@ -966,9 +975,9 @@ class fhandler_console: public fhandler_termios int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); - void doecho (const void *str, DWORD len) { (void) write (str, len); } void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); + ssize_t __stdcall write (const void *ptr, size_t len); + void doecho (const void *str, DWORD len) { (void) write (str, len); } int close (); int tcflush (int); @@ -1038,7 +1047,7 @@ class fhandler_tty_slave: public fhandler_tty_common fhandler_tty_slave (); int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); int init (HANDLE, DWORD, mode_t); @@ -1071,7 +1080,7 @@ public: void doecho (const void *str, DWORD len); int accept_input (); int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); int close (); @@ -1118,7 +1127,7 @@ class fhandler_dev_zero: public fhandler_base public: fhandler_dev_zero (); int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); _off64_t lseek (_off64_t offset, int whence); @@ -1145,7 +1154,7 @@ class fhandler_dev_random: public fhandler_base public: fhandler_dev_random (); int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); _off64_t lseek (_off64_t offset, int whence); int close (); @@ -1163,7 +1172,7 @@ class fhandler_dev_mem: public fhandler_base ~fhandler_dev_mem (); int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t ulen); + ssize_t __stdcall write (const void *ptr, size_t ulen); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); _off64_t lseek (_off64_t offset, int whence); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); @@ -1186,7 +1195,7 @@ class fhandler_dev_clipboard: public fhandler_base fhandler_dev_clipboard (); int is_windows () { return 1; } int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); _off64_t lseek (_off64_t offset, int whence); int close (); @@ -1204,7 +1213,7 @@ class fhandler_windows: public fhandler_base fhandler_windows (); int is_windows () { return 1; } int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); int ioctl (unsigned int cmd, void *); _off64_t lseek (_off64_t, int) { return 0; } @@ -1235,7 +1244,7 @@ class fhandler_dev_dsp: public fhandler_base fhandler_dev_dsp (); int open (int flags, mode_t mode = 0); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); int ioctl (unsigned int cmd, void *); _off64_t lseek (_off64_t, int); @@ -1266,7 +1275,7 @@ class fhandler_virtual : public fhandler_base void seekdir (DIR *, _off64_t); void rewinddir (DIR *); int closedir (DIR *); - int write (const void *ptr, size_t len); + ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); _off64_t lseek (_off64_t, int); int dup (fhandler_base *child); diff --git a/winsup/cygwin/fhandler_clipboard.cc b/winsup/cygwin/fhandler_clipboard.cc index 3750d16cd..c4f060578 100644 --- a/winsup/cygwin/fhandler_clipboard.cc +++ b/winsup/cygwin/fhandler_clipboard.cc @@ -143,7 +143,7 @@ set_clipboard (const void *buf, size_t len) } /* FIXME: arbitrary seeking is not handled */ -int +ssize_t __stdcall fhandler_dev_clipboard::write (const void *buf, size_t len) { if (!eof) diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 339b83cbf..5cc7e332f 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -1639,7 +1639,7 @@ fhandler_console::write_normal (const unsigned char *src, return found; } -int +ssize_t __stdcall fhandler_console::write (const void *vsrc, size_t len) { /* Run and check for ansi sequences */ diff --git a/winsup/cygwin/fhandler_dsp.cc b/winsup/cygwin/fhandler_dsp.cc index 1927a9b28..9095ba517 100644 --- a/winsup/cygwin/fhandler_dsp.cc +++ b/winsup/cygwin/fhandler_dsp.cc @@ -997,7 +997,7 @@ fhandler_dev_dsp::open (int flags, mode_t mode) #define IS_WRITE() ((get_flags() & O_ACCMODE) != O_RDONLY) #define IS_READ() ((get_flags() & O_ACCMODE) != O_WRONLY) -int +ssize_t __stdcall fhandler_dev_dsp::write (const void *ptr, size_t len) { debug_printf ("ptr=%08x len=%d", ptr, len); diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc index 517eceb31..d96616fc5 100644 --- a/winsup/cygwin/fhandler_fifo.cc +++ b/winsup/cygwin/fhandler_fifo.cc @@ -21,7 +21,7 @@ #include "cygtls.h" fhandler_fifo::fhandler_fifo (): - wait_state (fifo_unknown) + wait_state (fifo_unknown), dummy_client (NULL) { get_overlapped ()->hEvent = NULL; need_fork_fixup (true); @@ -54,80 +54,87 @@ fhandler_fifo::open_nonserver (const char *npname, unsigned low_flags, } } +char * +fhandler_fifo::fifo_name (char *buf) +{ + /* Generate a semi-unique name to associate with this fifo. */ + __small_sprintf (buf, "\\\\.\\pipe\\__cygfifo__%08x_%016X", + get_dev (), get_ino ()); + 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) + int fhandler_fifo::open (int flags, mode_t) { - int res; + int res = 1; char npname[MAX_PATH]; - DWORD mode = 0; - - /* Generate a semi-unique name to associate with this fifo. */ - __small_sprintf (npname, "\\\\.\\pipe\\__cygfifo__%08x_%016X", - get_dev (), get_ino ()); + fifo_name (npname); unsigned low_flags = flags & O_ACCMODE; - if (low_flags == O_RDONLY) - mode = PIPE_ACCESS_INBOUND; - else if (low_flags == O_WRONLY) + DWORD mode = 0; + if (low_flags == O_WRONLY) mode = PIPE_ACCESS_OUTBOUND; - else if (low_flags == O_RDWR) + else if (low_flags == O_RDONLY || low_flags == O_RDWR) mode = PIPE_ACCESS_DUPLEX; - - if (!mode) + else { set_errno (EINVAL); res = 0; } - else + + if (res) { char char_sa_buf[1024]; LPSECURITY_ATTRIBUTES sa_buf = sec_user ((PSECURITY_ATTRIBUTES) char_sa_buf, cygheap->user.sid()); - mode |= FILE_FLAG_OVERLAPPED; HANDLE h; - DWORD err; bool nonblocking_write = !!((flags & (O_WRONLY | O_NONBLOCK)) == (O_WRONLY | O_NONBLOCK)); - if (nonblocking_write) + wait_state = fifo_unknown; + if (mode != PIPE_ACCESS_OUTBOUND) { - h = INVALID_HANDLE_VALUE; - err = ERROR_ACCESS_DENIED; + h = cnp (mode | FILE_FLAG_OVERLAPPED, FIFO_BUF_SIZE); + wait_state = fifo_wait_for_client; } else { - h = CreateNamedPipe(npname, mode, FIFO_PIPE_MODE, - PIPE_UNLIMITED_INSTANCES, 0, 0, - NMPWAIT_WAIT_FOREVER, sa_buf); - err = GetLastError (); - } - if (h != INVALID_HANDLE_VALUE) - wait_state = fifo_wait_for_client; - else - switch (err) + h = open_nonserver (npname, low_flags, sa_buf); + if (h != INVALID_HANDLE_VALUE) + wait_state = fifo_ok; + else if (nonblocking_write) + set_errno (ENXIO); + else if ((h = cnp (PIPE_ACCESS_DUPLEX, 1)) != INVALID_HANDLE_VALUE) { - case ERROR_ACCESS_DENIED: - h = open_nonserver (npname, low_flags, sa_buf); - if (h != INVALID_HANDLE_VALUE) + if ((dummy_client = open_nonserver (npname, low_flags, sa_buf)) + != INVALID_HANDLE_VALUE) { wait_state = fifo_wait_for_server; - break; + ProtectHandle (dummy_client); } - if (nonblocking_write && GetLastError () == ERROR_FILE_NOT_FOUND) + else { - set_errno (ENXIO); - break; + DWORD saveerr = GetLastError (); + CloseHandle (h); + h = INVALID_HANDLE_VALUE; + SetLastError (saveerr); } - /* fall through intentionally */ - default: - __seterrno (); - break; } - if (!h || h == INVALID_HANDLE_VALUE) - res = 0; + } + if (h == INVALID_HANDLE_VALUE) + { + __seterrno (); + res = 0; + } else if (!setup_overlapped ()) { + CloseHandle (h); __seterrno (); res = 0; } @@ -146,35 +153,116 @@ fhandler_fifo::open (int flags, mode_t) bool fhandler_fifo::wait (bool iswrite) { + DWORD ninstances; switch (wait_state) { + case fifo_wait_for_next_client: + DisconnectNamedPipe (get_handle ()); + if (!GetNamedPipeHandleState (get_handle (), NULL, &ninstances, NULL, NULL, NULL, 0)) + { + __seterrno (); + wait_state = fifo_error; + return false; + } + if (ninstances <= 1) + { + wait_state = fifo_eof; + return false; + } case fifo_wait_for_client: { - bool res = ConnectNamedPipe (get_handle (), get_overlapped ()); DWORD dummy_bytes; - if (res || GetLastError () == ERROR_PIPE_CONNECTED) - return true; - return wait_overlapped (res, iswrite, &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); + 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; + } } - case fifo_unknown: + break; case fifo_wait_for_server: - /* CGF FIXME SOON: test if these really need to be handled. */ + char npname[MAX_PATH]; + fifo_name (npname); + char char_sa_buf[1024]; + LPSECURITY_ATTRIBUTES sa_buf; + sa_buf = sec_user ((PSECURITY_ATTRIBUTES) char_sa_buf, cygheap->user.sid()); + while (1) + { + if (WaitNamedPipe (npname, 10)) + /* connected, maybe */; + else if (GetLastError () != ERROR_SEM_TIMEOUT) + { + __seterrno (); + return false; + } + else if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0) + 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: break; } return true; } -void +void __stdcall fhandler_fifo::raw_read (void *in_ptr, size_t& len) { - if (!wait (false)) - len = 0; - else - read_overlapped (in_ptr, len); + while (wait_state != fifo_eof && wait_state != fifo_error && wait_state != fifo_eintr) + if (!wait (false)) + len = (wait_state == fifo_error || wait_state == fifo_eintr) ? (size_t) -1 : 0; + else + { + size_t prev_len = len; + read_overlapped (in_ptr, len); + if (len) + break; + wait_state = fifo_wait_for_next_client; + len = prev_len; + } + if (wait_state == fifo_eintr) + wait_state = fifo_wait_for_client; + debug_printf ("returning %d, mode %d, %E\n", len, get_errno ()); } -int +ssize_t __stdcall fhandler_fifo::raw_write (const void *ptr, size_t len) { return wait (true) ? write_overlapped (ptr, len) : -1; @@ -187,3 +275,44 @@ fhandler_fifo::fstatvfs (struct statvfs *sfs) fh.get_device () = FH_FS; return fh.fstatvfs (sfs); } + +int +fhandler_fifo::close () +{ + wait_state = fifo_eof; + if (dummy_client) + { + ForceCloseHandle (dummy_client); + dummy_client = NULL; + } + return fhandler_base::close (); +} + +int +fhandler_fifo::dup (fhandler_base *child) +{ + int res = fhandler_base::dup (child); + fhandler_fifo *fifo_child = (fhandler_fifo *) child; + if (res == 0 && dummy_client) + { + bool dres = DuplicateHandle (hMainProc, dummy_client, hMainProc, + &fifo_child->dummy_client, 0, + TRUE, DUPLICATE_SAME_ACCESS); + if (!dres) + { + fifo_child->dummy_client = NULL; + child->close (); + __seterrno (); + res = -1; + } + } + return res; +} + +void +fhandler_fifo::set_close_on_exec (bool val) +{ + fhandler_base::set_close_on_exec (val); + if (dummy_client) + set_no_inheritance (dummy_client, val); +} diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc index 5a78a731a..0d906b186 100644 --- a/winsup/cygwin/fhandler_floppy.cc +++ b/winsup/cygwin/fhandler_floppy.cc @@ -255,7 +255,7 @@ fhandler_dev_floppy::get_current_position () return off.QuadPart; } -void +void __stdcall fhandler_dev_floppy::raw_read (void *ptr, size_t& ulen) { DWORD bytes_read = 0; @@ -387,7 +387,7 @@ err: ulen = (size_t) -1; } -int +int __stdcall fhandler_dev_floppy::raw_write (const void *ptr, size_t len) { DWORD bytes_written = 0; diff --git a/winsup/cygwin/fhandler_mailslot.cc b/winsup/cygwin/fhandler_mailslot.cc index dda4d3385..c0813df94 100644 --- a/winsup/cygwin/fhandler_mailslot.cc +++ b/winsup/cygwin/fhandler_mailslot.cc @@ -124,7 +124,7 @@ fhandler_mailslot::open (int flags, mode_t mode) return res; } -int +ssize_t __stdcall fhandler_mailslot::write (const void *ptr, size_t len) { /* Check for 425/426 byte weirdness */ diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc index 752c114ed..7bd809472 100644 --- a/winsup/cygwin/fhandler_mem.cc +++ b/winsup/cygwin/fhandler_mem.cc @@ -113,7 +113,7 @@ fhandler_dev_mem::open (int flags, mode_t) return 1; } -int +ssize_t __stdcall fhandler_dev_mem::write (const void *ptr, size_t ulen) { if (!ulen || pos >= mem_size) diff --git a/winsup/cygwin/fhandler_random.cc b/winsup/cygwin/fhandler_random.cc index 09d70c554..e5d8a4866 100644 --- a/winsup/cygwin/fhandler_random.cc +++ b/winsup/cygwin/fhandler_random.cc @@ -68,7 +68,7 @@ fhandler_dev_random::pseudo_write (const void *ptr, size_t len) return len; } -int +ssize_t __stdcall fhandler_dev_random::write (const void *ptr, size_t len) { if (!len) diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc index 8a08beecc..a076dad1a 100644 --- a/winsup/cygwin/fhandler_serial.cc +++ b/winsup/cygwin/fhandler_serial.cc @@ -37,7 +37,7 @@ fhandler_serial::overlapped_setup () overlapped_armed = 0; } -void +void __stdcall fhandler_serial::raw_read (void *ptr, size_t& ulen) { int tot; @@ -144,7 +144,7 @@ out: /* Cover function to WriteFile to provide Posix interface and semantics (as much as possible). */ -int +ssize_t __stdcall fhandler_serial::raw_write (const void *ptr, size_t len) { DWORD bytes_written; diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc index 57f918557..d90810f89 100644 --- a/winsup/cygwin/fhandler_tape.cc +++ b/winsup/cygwin/fhandler_tape.cc @@ -1232,7 +1232,7 @@ fhandler_dev_tape::close () return ret ? -1 : cret; } -void +void __stdcall fhandler_dev_tape::raw_read (void *ptr, size_t &ulen) { char *buf = (char *) ptr; @@ -1333,7 +1333,7 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen) unlock (); } -int +ssize_t __stdcall fhandler_dev_tape::raw_write (const void *ptr, size_t len) { lock (-1); diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index ae857e9ef..fbb766c3f 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -671,7 +671,7 @@ fhandler_tty_slave::init (HANDLE, DWORD a, mode_t) return open (flags); } -int +ssize_t __stdcall fhandler_tty_slave::write (const void *ptr, size_t len) { DWORD n, towrite = len; @@ -1202,7 +1202,7 @@ fhandler_pty_master::close () return 0; } -int +ssize_t __stdcall fhandler_pty_master::write (const void *ptr, size_t len) { int i; diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc index b11d596e0..c47d2ccdd 100644 --- a/winsup/cygwin/fhandler_virtual.cc +++ b/winsup/cygwin/fhandler_virtual.cc @@ -180,7 +180,7 @@ fhandler_virtual::close () return 0; } -void +void __stdcall fhandler_virtual::read (void *ptr, size_t& len) { if (len == 0) @@ -205,7 +205,7 @@ fhandler_virtual::read (void *ptr, size_t& len) position += len; } -int +ssize_t __stdcall fhandler_virtual::write (const void *ptr, size_t len) { set_errno (EACCES); diff --git a/winsup/cygwin/fhandler_windows.cc b/winsup/cygwin/fhandler_windows.cc index 09ce3a017..7475b89bb 100644 --- a/winsup/cygwin/fhandler_windows.cc +++ b/winsup/cygwin/fhandler_windows.cc @@ -60,7 +60,7 @@ fhandler_windows::open (int flags, mode_t) return 1; } -int +ssize_t __stdcall fhandler_windows::write (const void *buf, size_t) { MSG *ptr = (MSG *) buf; diff --git a/winsup/cygwin/fhandler_zero.cc b/winsup/cygwin/fhandler_zero.cc index 41d1dcdca..a27c0f6ec 100644 --- a/winsup/cygwin/fhandler_zero.cc +++ b/winsup/cygwin/fhandler_zero.cc @@ -30,7 +30,7 @@ fhandler_dev_zero::open (int flags, mode_t) return 1; } -int +ssize_t __stdcall fhandler_dev_zero::write (const void *, size_t len) { if (get_device () == FH_FULL) diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index cdaaca649..49ff2e1ab 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -242,7 +242,7 @@ frok::child (volatile char * volatile here) ld_preload (); fixup_hooks_after_fork (); _my_tls.fixup_after_fork (); - wait_for_sigthread (true); + wait_for_sigthread (); cygwin_finished_initializing = true; return 0; } diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 29bb00101..9c11ea022 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -128,24 +128,16 @@ signal_fixup_after_exec () } void __stdcall -wait_for_sigthread (bool forked) +wait_for_sigthread () { - char char_sa_buf[1024]; - PSECURITY_ATTRIBUTES sa_buf = sec_user_nih ((PSECURITY_ATTRIBUTES) char_sa_buf, cygheap->user.sid()); - if (!CreatePipe (&my_readsig, &my_sendsig, sa_buf, 0)) - api_fatal ("couldn't create signal pipe%s, %E", forked ? " for forked process" : ""); - ProtectHandle (my_readsig); - myself->sendsig = my_sendsig; - - myself->process_state |= PID_ACTIVE; - myself->process_state &= ~PID_INITIALIZING; - sigproc_printf ("wait_sig_inited %p", wait_sig_inited); HANDLE hsig_inited = wait_sig_inited; WaitForSingleObject (hsig_inited, INFINITE); wait_sig_inited = NULL; + myself->sendsig = my_sendsig; + myself->process_state |= PID_ACTIVE; + myself->process_state &= ~PID_INITIALIZING; ForceCloseHandle1 (hsig_inited, wait_sig_inited); - SetEvent (sigCONT); sigproc_printf ("process/signal handling enabled, state %p", myself->process_state); } @@ -1152,11 +1144,28 @@ pending_signals::next () return res; } +/* Called separately to allow stack space reutilization by wait_sig. + This function relies on the fact that it will be called after cygheap + has been set up. For the case of non-dynamic DLL initialization this + means that it relies on the implicit serialization guarantted by being + run as part of DLL_PROCESS_ATTACH. */ +static void __attribute__ ((noinline)) +init_sig_pipe() +{ + char char_sa_buf[1024]; + PSECURITY_ATTRIBUTES sa_buf = sec_user_nih ((PSECURITY_ATTRIBUTES) char_sa_buf, cygheap->user.sid()); + if (!CreatePipe (&my_readsig, &my_sendsig, sa_buf, 0)) + api_fatal ("couldn't create signal pipe, %E"); + ProtectHandle (my_readsig); +} + + /* Process signals by waiting for signal data to arrive in a pipe. Set a completion event if one was specified. */ static DWORD WINAPI wait_sig (VOID *) { + init_sig_pipe (); /* Initialization */ SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY); @@ -1169,7 +1178,7 @@ wait_sig (VOID *) my_readsig, my_sendsig); sigpacket pack; - pack.si.si_signo = __SIGHOLD; + pack.si.si_signo = 0; for (;;) { if (pack.si.si_signo == __SIGHOLD) diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 5fef01d7a..7da1bc389 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -81,7 +81,7 @@ bool __stdcall pid_exists (pid_t) __attribute__ ((regparm(1))); int __stdcall sig_send (_pinfo *, siginfo_t&, class _cygtls *tls = NULL) __attribute__ ((regparm (3))); int __stdcall sig_send (_pinfo *, int) __attribute__ ((regparm (2))); void __stdcall signal_fixup_after_exec (); -void __stdcall wait_for_sigthread (bool = false); +void __stdcall wait_for_sigthread (); void __stdcall sigalloc (); void __stdcall create_signal_arrived (); diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index eea65907b..fb17f1e2a 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -842,7 +842,7 @@ readv (int fd, const struct iovec *const iov, const int iovcnt) extern int sigcatchers; const int e = get_errno (); - int res = -1; + ssize_t res = -1; const ssize_t tot = check_iovec_for_read (iov, iovcnt);