[newlib-cygwin] Cygwin: AF_UNIX: Implement read, readv, recvfrom, write, writev, sendto
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=5bb4cc1e6cfba2d3246bd72c419e89c54b15ad56 commit 5bb4cc1e6cfba2d3246bd72c419e89c54b15ad56 Author: Corinna VinschenDate: Wed Mar 7 21:53:56 2018 +0100 Cygwin: AF_UNIX: Implement read, readv, recvfrom, write, writev, sendto All of these functions just call recvfrom/sendmsg which are still TODO Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 108 +++--- 1 file changed, 88 insertions(+), 20 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 6eca668..d27cdad 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -1545,18 +1545,33 @@ fhandler_socket_unix::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid) } ssize_t -fhandler_socket_unix::recvfrom (void *ptr, size_t len, int flags, - struct sockaddr *from, int *fromlen) +fhandler_socket_unix::recvmsg (struct msghdr *msg, int flags) { set_errno (EAFNOSUPPORT); return -1; } ssize_t -fhandler_socket_unix::recvmsg (struct msghdr *msg, int flags) +fhandler_socket_unix::recvfrom (void *ptr, size_t len, int flags, + struct sockaddr *from, int *fromlen) { - set_errno (EAFNOSUPPORT); - return -1; + struct iovec iov; + struct msghdr msg; + ssize_t ret; + + iov.iov_base = ptr; + iov.iov_len = len; + msg.msg_name = from; + msg.msg_namelen = from && fromlen ? *fromlen : 0; + msg.msg_iov = + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + ret = recvmsg (, flags); + if (ret >= 0 && from && fromlen) +*fromlen = msg.msg_namelen; + return ret; } void __reg3 @@ -1564,42 +1579,95 @@ fhandler_socket_unix::read (void *ptr, size_t& len) { set_errno (EAFNOSUPPORT); len = 0; + struct iovec iov; + struct msghdr msg; + + iov.iov_base = ptr; + iov.iov_len = len; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + len = recvmsg (, 0); } ssize_t __stdcall -fhandler_socket_unix::readv (const struct iovec *, int iovcnt, ssize_t tot) -{ - set_errno (EAFNOSUPPORT); - return -1; +fhandler_socket_unix::readv (const struct iovec *const iov, int iovcnt, +ssize_t tot) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = (struct iovec *) iov; + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return recvmsg (, 0); } ssize_t -fhandler_socket_unix::sendto (const void *in_ptr, size_t len, int flags, - const struct sockaddr *to, int tolen) +fhandler_socket_unix::sendmsg (const struct msghdr *msg, int flags) { set_errno (EAFNOSUPPORT); return -1; } ssize_t -fhandler_socket_unix::sendmsg (const struct msghdr *msg, int flags) +fhandler_socket_unix::sendto (const void *in_ptr, size_t len, int flags, + const struct sockaddr *to, int tolen) { - set_errno (EAFNOSUPPORT); - return -1; + struct iovec iov; + struct msghdr msg; + + iov.iov_base = (void *) in_ptr; + iov.iov_len = len; + msg.msg_name = (void *) to; + msg.msg_namelen = to ? tolen : 0; + msg.msg_iov = + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return sendmsg (, flags); } ssize_t __stdcall fhandler_socket_unix::write (const void *ptr, size_t len) { - set_errno (EAFNOSUPPORT); - return -1; + struct iovec iov; + struct msghdr msg; + + iov.iov_base = (void *) ptr; + iov.iov_len = len; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return sendmsg (, 0); } ssize_t __stdcall -fhandler_socket_unix::writev (const struct iovec *, int iovcnt, ssize_t tot) -{ - set_errno (EAFNOSUPPORT); - return -1; +fhandler_socket_unix::writev (const struct iovec *const iov, int iovcnt, + ssize_t tot) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = (struct iovec *) iov; + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return sendmsg (, 0); } int
[newlib-cygwin] Cygwin: AF_UNIX: define AF_UNIX_CONNECT_TIMEOUT
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=483cbf89549545051717d3afabadf31c9c70c2f5 commit 483cbf89549545051717d3afabadf31c9c70c2f5 Author: Corinna VinschenDate: Wed Mar 7 21:55:34 2018 +0100 Cygwin: AF_UNIX: define AF_UNIX_CONNECT_TIMEOUT Use macro AF_UNIX_CONNECT_TIMEOUT instead of numerical constant for connect timeout. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index d27cdad..afd57fc 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -154,6 +154,9 @@ GUID __cygwin_socket_guid = { _s == STATUS_BUFFER_OVERFLOW \ || _s == STATUS_MORE_PROCESSING_REQUIRED; }) +/* Default timeout value of connect: 20 secs, as on Linux. */ +#define AF_UNIX_CONNECT_TIMEOUT (-20 * NS100PERSEC) + sun_name_t::sun_name_t () { un_len = sizeof (sa_family_t); @@ -619,7 +622,7 @@ fhandler_socket_unix::recv_peer_name () DWORD ret; LARGE_INTEGER timeout; - timeout.QuadPart = -20 * NS100PERSEC;/* 20 secs */ + timeout.QuadPart = AF_UNIX_CONNECT_TIMEOUT; ret = cygwait (evt, , cw_sig_eintr); switch (ret) { @@ -1062,7 +1065,7 @@ fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name) goto out; pwbuf_size = offsetof (FILE_PIPE_WAIT_FOR_BUFFER, Name) + pipe_name->Length; pwbuf = (PFILE_PIPE_WAIT_FOR_BUFFER) alloca (pwbuf_size); - pwbuf->Timeout.QuadPart = -20 * NS100PERSEC; /* 20 secs */ + pwbuf->Timeout.QuadPart = AF_UNIX_CONNECT_TIMEOUT; pwbuf->NameLength = pipe_name->Length; pwbuf->TimeoutSpecified = TRUE; memcpy (pwbuf->Name, pipe_name->Buffer, pipe_name->Length);
[newlib-cygwin] Cygwin: Define FSCTL_PIPE_FLUSH
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=2f48ddb1ca45055eaeaa61af766653251b575a72 commit 2f48ddb1ca45055eaeaa61af766653251b575a72 Author: Corinna VinschenDate: Wed Mar 7 21:54:46 2018 +0100 Cygwin: Define FSCTL_PIPE_FLUSH This fsctl might come in handy at one point... Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/ntdll.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index b251055..64babef 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -157,6 +157,7 @@ extern GUID __cygwin_socket_guid; #define FILE_VC_VALID_MASK 0x03ff /* IOCTL code to impersonate client of named pipe. */ + #define FSCTL_PIPE_DISCONNECT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 1, \ METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, \ @@ -165,6 +166,8 @@ extern GUID __cygwin_socket_guid; METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSCTL_PIPE_IMPERSONATE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 7, \ METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_FLUSH CTL_CODE(FILE_DEVICE_NAMED_PIPE, 16, \ +METHOD_BUFFERED, FILE_WRITE_DATA) typedef enum _FILE_INFORMATION_CLASS {
[newlib-cygwin] Cygwin: reorder read/write calls in fhandler_socket_unix
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=d7f7d292d83e2a3cd41d8da66d5abe0951b331b0 commit d7f7d292d83e2a3cd41d8da66d5abe0951b331b0 Author: Corinna VinschenDate: Wed Mar 7 21:52:29 2018 +0100 Cygwin: reorder read/write calls in fhandler_socket_unix Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler.h | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 13f4068..7d45aa0 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -922,18 +922,19 @@ class fhandler_socket_unix : public fhandler_socket int shutdown (int how); int close (); int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); + ssize_t recvmsg (struct msghdr *msg, int flags); ssize_t recvfrom (void *ptr, size_t len, int flags, struct sockaddr *from, int *fromlen); - ssize_t recvmsg (struct msghdr *msg, int flags); void __reg3 read (void *ptr, size_t& len); - ssize_t __stdcall readv (const struct iovec *, int iovcnt, + ssize_t __stdcall readv (const struct iovec *const iov, int iovcnt, ssize_t tot = -1); + ssize_t sendmsg (const struct msghdr *msg, int flags); ssize_t sendto (const void *ptr, size_t len, int flags, const struct sockaddr *to, int tolen); - ssize_t sendmsg (const struct msghdr *msg, int flags); ssize_t __stdcall write (const void *ptr, size_t len); - ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1); + ssize_t __stdcall writev (const struct iovec *const iov, int iovcnt, + ssize_t tot = -1); int setsockopt (int level, int optname, const void *optval, __socklen_t optlen); int getsockopt (int level, int optname, const void *optval,
[newlib-cygwin] Cygwin: AF_UNIX: implement getsockopt SO_RCVBUF/SO_SNDBUF
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=7d525c171f79243de864d7a736d1cf85209b62db commit 7d525c171f79243de864d7a736d1cf85209b62db Author: Corinna VinschenDate: Wed Mar 7 21:56:42 2018 +0100 Cygwin: AF_UNIX: implement getsockopt SO_RCVBUF/SO_SNDBUF Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 10 ++ 1 file changed, 10 insertions(+) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index afd57fc..388fbdf 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -1780,6 +1780,16 @@ fhandler_socket_unix::getsockopt (int level, int optname, const void *optval, break; } + case SO_RCVBUF: + case SO_SNDBUF: + if (*optlen < (socklen_t) sizeof (int)) + { + set_errno (EINVAL); + return -1; + } + *(int *) optval = (optname == SO_RCVBUF) ? rmem () : wmem (); + break; + case SO_RCVTIMEO: case SO_SNDTIMEO: {
[newlib-cygwin] describe new locale modifier @cjkwide for user guide
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=e4c65b2e918107287845ab345bc0607bde0323f7 commit e4c65b2e918107287845ab345bc0607bde0323f7 Author: Thomas WolffDate: Thu Mar 8 00:29:25 2018 +0100 describe new locale modifier @cjkwide for user guide Diff: --- winsup/doc/setup-locale.xml | 13 + 1 file changed, 13 insertions(+) diff --git a/winsup/doc/setup-locale.xml b/winsup/doc/setup-locale.xml index 29502a2..4872ae2 100644 --- a/winsup/doc/setup-locale.xml +++ b/winsup/doc/setup-locale.xml @@ -166,6 +166,19 @@ can be used to force wcwidth/wcswidth to return 1 for the ambiguous width characters. + +For the same class of "CJK Ambiguous Width" characters, it may be +desirable to handle them as double-width even when a non-CJK language +setting is selected. This supports e.g. certain graphic symbols used +by "Powerline" and provided by "Powerline fonts". Some terminals have +options to enforce this width handling (xterm -cjk_width, +mintty -o Charwidth=ambig-wide, putty configuration) but that alone +makes character rendering and locale information inconsistent for those +characters. The locale modifier "@cjkwide" supports consistent locale +response with this option; it forces wcwidth/wcswidth to return 2 for the +ambiguous width characters. + +
[newlib-cygwin] Cygwin: AF_UNIX: fix SEGV when sending an empty socket name from connect
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=4de52a0fe1009d2a5318a731400dbf4280b184cc commit 4de52a0fe1009d2a5318a731400dbf4280b184cc Author: Corinna VinschenDate: Wed Mar 7 16:08:15 2018 +0100 Cygwin: AF_UNIX: fix SEGV when sending an empty socket name from connect Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index f320453..27ac958 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -540,15 +540,18 @@ fhandler_socket_unix::set_pipe_non_blocking (bool nonblocking) int fhandler_socket_unix::send_my_name () { + sun_name_t *sun; size_t name_len = 0; af_unix_pkt_hdr_t *packet; NTSTATUS status; IO_STATUS_BLOCK io; AcquireSRWLockShared (_lock); - name_len = get_sun_path ()->un_len; + sun = get_sun_path (); + name_len = sun ? sun->un_len : 0; packet = (af_unix_pkt_hdr_t *) alloca (sizeof *packet + name_len); - memcpy (AF_UNIX_PKT_NAME (packet), _sun_path ()->un, name_len); + if (sun) +memcpy (AF_UNIX_PKT_NAME (packet), >un, name_len); ReleaseSRWLockShared (_lock); packet->init (0, name_len, 0, 0);
[newlib-cygwin] Cygwin: AF_UNIX: fix creation of npfs handle
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=2f2a75b7bbf521057f3e8e502f1a6641a2baf376 commit 2f2a75b7bbf521057f3e8e502f1a6641a2baf376 Author: Corinna VinschenDate: Wed Mar 7 15:48:21 2018 +0100 Cygwin: AF_UNIX: fix creation of npfs handle The handle to the device is never needed. As the name impies, FSCTL_PIPE_WAIT works on the file system, not on the device level. Drop opening the device and make sure to open only one handle to NPFS. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler.h | 8 +--- winsup/cygwin/fhandler_socket_unix.cc | 37 --- winsup/cygwin/globals.cc | 3 +-- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 392ba6c..4166126 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -852,12 +852,6 @@ class sun_name_t class fhandler_socket_unix : public fhandler_socket { - enum npfs_hdl_t - { - NPFS_DEVICE, - NPFS_DIR - }; - protected: SRWLOCK conn_lock; SRWLOCK bind_lock; @@ -886,7 +880,7 @@ class fhandler_socket_unix : public fhandler_socket void set_pipe_non_blocking (bool nonblocking); int send_my_name (); int recv_peer_name (); - static NTSTATUS npfs_handle (HANDLE , npfs_hdl_t type); + static NTSTATUS npfs_handle (HANDLE ); HANDLE create_pipe (); HANDLE create_pipe_instance (); NTSTATUS open_pipe (HANDLE , PUNICODE_STRING pipe_name); diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index ea8aece..f320453 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -620,28 +620,33 @@ fhandler_socket_unix::recv_peer_name () } NTSTATUS -fhandler_socket_unix::npfs_handle (HANDLE , npfs_hdl_t type) +fhandler_socket_unix::npfs_handle (HANDLE ) { - static NO_COPY HANDLE npfs_devh; + static NO_COPY SRWLOCK npfs_lock; static NO_COPY HANDLE npfs_dirh; - HANDLE _ref = (type == NPFS_DEVICE) ? npfs_devh : npfs_dirh; - PUNICODE_STRING path = (type == NPFS_DEVICE) ? _u_npfs : _u_npfs_dir; - NTSTATUS status; + NTSTATUS status = STATUS_SUCCESS; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK io; - if (!npfs_ref) + /* Lockless after first call. */ + if (npfs_dirh) +{ + nph = npfs_dirh; + return STATUS_SUCCESS; +} + AcquireSRWLockExclusive (_lock); + if (!npfs_dirh) { - InitializeObjectAttributes (, path, 0, NULL, NULL); - status = NtOpenFile (_ref, FILE_READ_ATTRIBUTES | SYNCHRONIZE, + InitializeObjectAttributes (, _u_npfs, 0, NULL, NULL); + status = NtOpenFile (_dirh, FILE_READ_ATTRIBUTES | SYNCHRONIZE, , , FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS (status)) - return status; } - nph = npfs_ref; - return STATUS_SUCCESS; + ReleaseSRWLockExclusive (_lock); + if (NT_SUCCESS (status)) +nph = npfs_dirh; + return status; } HANDLE @@ -658,7 +663,7 @@ fhandler_socket_unix::create_pipe () ULONG max_instances; LARGE_INTEGER timeout; - status = npfs_handle (npfsh, NPFS_DIR); + status = npfs_handle (npfsh); if (!NT_SUCCESS (status)) { __seterrno_from_nt_status (status); @@ -700,7 +705,7 @@ fhandler_socket_unix::create_pipe_instance () ULONG max_instances; LARGE_INTEGER timeout; - status = npfs_handle (npfsh, NPFS_DIR); + status = npfs_handle (npfsh); if (!NT_SUCCESS (status)) { __seterrno_from_nt_status (status); @@ -738,7 +743,7 @@ fhandler_socket_unix::open_pipe (HANDLE , PUNICODE_STRING pipe_name) IO_STATUS_BLOCK io; ULONG sharing; - status = npfs_handle (npfsh, NPFS_DIR); + status = npfs_handle (npfsh); if (!NT_SUCCESS (status)) return status; access = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE; @@ -996,7 +1001,7 @@ fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name) LONGLONG stamp; HANDLE ph = NULL; - status = npfs_handle (npfsh, NPFS_DEVICE); + status = npfs_handle (npfsh); if (!NT_SUCCESS (status)) { error = geterrno_from_nt_status (status); diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index 9dac030..7c84eb6 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -149,8 +149,7 @@ const int __collate_load_error = 0; extern UNICODE_STRING _RDATA ro_u_natdir = _ROU (L"Directory"); extern UNICODE_STRING _RDATA ro_u_natsyml = _ROU (L"SymbolicLink"); extern UNICODE_STRING _RDATA ro_u_natdev = _ROU (L"Device"); - extern UNICODE_STRING _RDATA ro_u_npfs = _ROU (L"\\Device\\NamedPipe"); - extern UNICODE_STRING _RDATA ro_u_npfs_dir = _ROU (L"\\Device\\NamedPipe\\"); + extern UNICODE_STRING _RDATA ro_u_npfs = _ROU (L"\\Device\\NamedPipe\\"); #undef _ROU /* This is an exported copy
[newlib-cygwin] Cygwin: AF_UNIX: Add create_event helper and use throughout
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=d69bcdd671539caea906f18e327dfd2eb9f1da85 commit d69bcdd671539caea906f18e327dfd2eb9f1da85 Author: Corinna VinschenDate: Wed Mar 7 16:00:36 2018 +0100 Cygwin: AF_UNIX: Add create_event helper and use throughout Minimize overhead in creating a nameless event object. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 40 ++- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index d5f617d..ea8aece 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -148,6 +148,24 @@ sun_name_t::sun_name_t (const struct sockaddr *name, socklen_t namelen) _nul[sizeof (struct sockaddr_un)] = '\0'; } +static HANDLE +create_event () +{ + NTSTATUS status; + OBJECT_ATTRIBUTES attr; + HANDLE evt = NULL; + + InitializeObjectAttributes (, NULL, 0, NULL, NULL); + status = NtCreateEvent (, EVENT_ALL_ACCESS, , + NotificationEvent, FALSE); + if (!NT_SUCCESS (status)) +__seterrno_from_nt_status (status); + return evt; +} + +/* Character length of pipe name, excluding trailing NUL. */ +#define CYGWIN_PIPE_SOCKET_NAME_LEN 47 + /* Character position encoding the socket type in a pipe name. */ #define CYGWIN_PIPE_SOCKET_TYPE_POS29 @@ -555,6 +573,7 @@ fhandler_socket_unix::send_my_name () int fhandler_socket_unix::recv_peer_name () { + HANDLE evt; NTSTATUS status; IO_STATUS_BLOCK io; af_unix_pkt_hdr_t *packet; @@ -562,10 +581,12 @@ fhandler_socket_unix::recv_peer_name () ULONG len; int ret = 0; + if (!(evt = create_event ())) +return ENOBUFS; len = sizeof *packet + sizeof *un; packet = (af_unix_pkt_hdr_t *) alloca (len); set_pipe_non_blocking (false); - status = NtReadFile (get_handle (), NULL, NULL, NULL, , packet, len, + status = NtReadFile (get_handle (), evt, NULL, NULL, , packet, len, NULL, NULL); if (status == STATUS_PENDING) { @@ -573,7 +594,7 @@ fhandler_socket_unix::recv_peer_name () LARGE_INTEGER timeout; timeout.QuadPart = -20 * NS100PERSEC;/* 20 secs */ - ret = cygwait (connect_wait_thr, , cw_sig_eintr); + ret = cygwait (evt, , cw_sig_eintr); switch (ret) { case WAIT_OBJECT_0: @@ -835,22 +856,11 @@ fhandler_socket_unix::listen_pipe () { NTSTATUS status; IO_STATUS_BLOCK io; - OBJECT_ATTRIBUTES attr; HANDLE evt = NULL; io.Status = STATUS_PENDING; - if (!is_nonblocking ()) -{ - /* Create event object and set APC context pointer. */ - InitializeObjectAttributes (, NULL, 0, NULL, NULL); - status = NtCreateEvent (, EVENT_ALL_ACCESS, , - NotificationEvent, FALSE); - if (!NT_SUCCESS (status)) - { - __seterrno_from_nt_status (status); - return -1; - } -} + if (!is_nonblocking () && !(evt = create_event ())) +return -1; status = NtFsControlFile (get_handle (), evt, NULL, NULL, , FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0); if (status == STATUS_PENDING)
[newlib-cygwin] Cygwin: AF_UNIX: make sure connect wait thread is cleanly interruptible
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=cde2648c2250eb373d1e245160e2aca26dc0555c commit cde2648c2250eb373d1e245160e2aca26dc0555c Author: Corinna VinschenDate: Wed Mar 7 16:19:32 2018 +0100 Cygwin: AF_UNIX: make sure connect wait thread is cleanly interruptible Using TerminateThread potentially leaks resources. In our case, the connect wait thread may be forcefully terminated after having successfully opened a client side pipe handle. If this occurs, we have a stale pipe server instance, so the pipe will never be closed as long as the process lives. Avoid this by changing the npfs handle to non-blocking, so we can wait on a termination event object from inside the thread itself and cleanly exit from the thread instead of terminating. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler.h | 1 + winsup/cygwin/fhandler_socket_unix.cc | 56 ++- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 4166126..13f4068 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -860,6 +860,7 @@ class fhandler_socket_unix : public fhandler_socket if the socket is backed by a file in the file system (actually a reparse point) */ HANDLE connect_wait_thr; + HANDLE cwt_termination_evt; PVOID cwt_param; LONG so_error; sun_name_t *sun_path; diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 099000d..dcd4938 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -667,7 +667,7 @@ fhandler_socket_unix::npfs_handle (HANDLE ) InitializeObjectAttributes (, _u_npfs, 0, NULL, NULL); status = NtOpenFile (_dirh, FILE_READ_ATTRIBUTES | SYNCHRONIZE, , , FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_SYNCHRONOUS_IO_NONALERT); + 0); } ReleaseSRWLockExclusive (_lock); if (NT_SUCCESS (status)) @@ -808,7 +808,11 @@ fhandler_socket_unix::wait_pipe (PUNICODE_STRING pipe_name) conn_wait_info_t *wait_info; DWORD waitret, err; int ret = -1; + HANDLE thr, evt; + PVOID param; + if (!(cwt_termination_evt = create_event ())) + return -1; wait_info = (conn_wait_info_t *) cmalloc_abort (HEAP_FHANDLER, sizeof *wait_info); wait_info->fh = this; @@ -823,23 +827,28 @@ fhandler_socket_unix::wait_pipe (PUNICODE_STRING pipe_name) { cfree (wait_info); __seterrno (); - return -1; + goto out; } if (is_nonblocking ()) { set_errno (EINPROGRESS); - return -1; + goto out; } waitret = cygwait (connect_wait_thr, cw_infinite, cw_cancel | cw_sig_eintr); if (waitret == WAIT_OBJECT_0) GetExitCodeThread (connect_wait_thr, ); else -TerminateThread (connect_wait_thr, 0); - HANDLE thr = InterlockedExchangePointer (_wait_thr, NULL); +{ + SetEvent (cwt_termination_evt); + WaitForSingleObject (connect_wait_thr, INFINITE); + GetExitCodeThread (connect_wait_thr, ); + waitret = WAIT_SIGNALED; +} + thr = InterlockedExchangePointer (_wait_thr, NULL); if (thr) CloseHandle (thr); - PVOID param = InterlockedExchangePointer (_param, NULL); + param = InterlockedExchangePointer (_param, NULL); if (param) cfree (param); switch (waitret) @@ -858,6 +867,10 @@ fhandler_socket_unix::wait_pipe (PUNICODE_STRING pipe_name) ret = 0; break; } +out: + evt = InterlockedExchangePointer (_termination_evt, NULL); + if (evt) +NtClose (evt); return ret; } @@ -965,6 +978,7 @@ fhandler_socket_unix::fixup_after_fork (HANDLE parent) InitializeSRWLock (_lock); InitializeSRWLock (_lock); connect_wait_thr = NULL; + cwt_termination_evt = NULL; cwt_param = NULL; } @@ -1001,6 +1015,7 @@ fhandler_socket_unix::dup (fhandler_base *child, int flags) InitializeSRWLock (>bind_lock); InitializeSRWLock (>io_lock); fhs->connect_wait_thr = NULL; + fhs->cwt_termination_evt = NULL; fhs->cwt_param = NULL; return fhandler_socket::dup (child, flags); } @@ -1019,6 +1034,7 @@ DWORD fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name) { HANDLE npfsh; + HANDLE evt; LONG error = 0; NTSTATUS status; IO_STATUS_BLOCK io; @@ -1033,6 +1049,8 @@ fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name) error = geterrno_from_nt_status (status); goto out; } + if (!(evt = create_event ())) +goto out; pwbuf_size = offsetof (FILE_PIPE_WAIT_FOR_BUFFER, Name) + pipe_name->Length; pwbuf = (PFILE_PIPE_WAIT_FOR_BUFFER) alloca (pwbuf_size); pwbuf->Timeout.QuadPart = -20 * NS100PERSEC; /* 20 secs */ @@ -1042,8
[newlib-cygwin] Cygwin: AF_UNIX: fix accept behaviour
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=855e5d7e144ac1e302087cf08c37eec13c62f75a commit 855e5d7e144ac1e302087cf08c37eec13c62f75a Author: Corinna VinschenDate: Wed Mar 7 16:23:44 2018 +0100 Cygwin: AF_UNIX: fix accept behaviour * Use correct cygwait/WFSO invocation to not die on cancel and signals uncontrolled. * Manage io handles under io_lock. * Copy peer address to user space under SEH to avoid a resource leak. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 52 +-- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index dcd4938..6eca668 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -901,6 +901,7 @@ fhandler_socket_unix::listen_pipe () NTSTATUS status; IO_STATUS_BLOCK io; HANDLE evt = NULL; + DWORD waitret = WAIT_OBJECT_0; io.Status = STATUS_PENDING; if (!is_nonblocking () && !(evt = create_event ())) @@ -909,12 +910,18 @@ fhandler_socket_unix::listen_pipe () FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0); if (status == STATUS_PENDING) { - if (cygwait (evt ?: get_handle ()) == WAIT_OBJECT_0) + waitret = cygwait (evt ?: get_handle (), cw_infinite, +cw_cancel | cw_sig_eintr); + if (waitret == WAIT_OBJECT_0) status = io.Status; } if (evt) NtClose (evt); - if (status == STATUS_PIPE_LISTENING) + if (waitret == WAIT_CANCELED) +pthread::static_cancel_self (); + else if (waitret == WAIT_SIGNALED) +set_errno (EINTR); + else if (status == STATUS_PIPE_LISTENING) set_errno (EAGAIN); else if (status != STATUS_PIPE_CONNECTED) __seterrno_from_nt_status (status); @@ -929,7 +936,9 @@ fhandler_socket_unix::disconnect_pipe (HANDLE ph) status = NtFsControlFile (ph, NULL, NULL, NULL, , FSCTL_PIPE_DISCONNECT, NULL, 0, NULL, 0); - if (status == STATUS_PENDING && cygwait (ph) == WAIT_OBJECT_0) + /* Short-lived. Don't use cygwait. We don't want to be interrupted. */ + if (status == STATUS_PENDING + && WaitForSingleObject (ph, INFINITE) == WAIT_OBJECT_0) status = io.Status; if (!NT_SUCCESS (status)) { @@ -1290,13 +1299,17 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags) /* Our handle is now connected with a client. This handle is used for the accepted socket. Our handle has to be replaced with a new instance handle for the next accept. */ + AcquireSRWLockExclusive (_lock); HANDLE accepted = get_handle (); HANDLE new_inst = create_pipe_instance (); int error = ENOBUFS; - if (new_inst) + if (!new_inst) + ReleaseSRWLockExclusive (_lock); + else { /* Set new io handle. */ set_io_handle (new_inst); + ReleaseSRWLockExclusive (_lock); /* Prepare new file descriptor. */ cygheap_fdnew fd; @@ -1323,21 +1336,30 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags) error = sock->recv_peer_name (); if (error == 0) { - if (peer) + __try { - sun_name_t *sun = sock->get_peer_sun_path (); - if (sun) + if (peer) { - memcpy (peer, >un, MIN (*len, sun->un_len)); - *len = sun->un_len; + sun_name_t *sun = sock->get_peer_sun_path (); + if (sun) + { + memcpy (peer, >un, + MIN (*len, sun->un_len)); + *len = sun->un_len; + } + else if (len) + *len = 0; } - else if (len) - *len = 0; + fd = sock; + if (fd <= 2) + set_std_handle (fd); + return fd; + } + __except (NO_ERROR) + { + error = EFAULT; } - fd = sock; - if (fd <= 2) - set_std_handle (fd); - return fd; + __endtry } delete sock; }
[newlib-cygwin] Cygwin: AF_UNIX: fix comments and move a macro
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=e94fa4ebf39384446f89a44b3769756fb51cb4f9 commit e94fa4ebf39384446f89a44b3769756fb51cb4f9 Author: Corinna VinschenDate: Wed Mar 7 15:43:26 2018 +0100 Cygwin: AF_UNIX: fix comments and move a macro Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index ae422dd..d5f617d 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -67,12 +67,12 @@ for the entire packet, as well as for all three data blocks. The combined maximum size of a packet is 64K, including the header. - A connecting, bound STREAM socket send it's local sun_path once after + A connecting, bound STREAM socket sends it's local sun_path once after a successful connect. An already connected socket also sends its local sun_path after a successful bind (border case, but still...). These packages don't contain any other data (cmsg_len == 0, data_len == 0). - A bound DGRAM socket send its sun_path with each sendmsg/sendto. + A bound DGRAM socket sends its sun_path with each sendmsg/sendto. */ class af_unix_pkt_hdr_t { @@ -124,9 +124,6 @@ class af_unix_pkt_hdr_t (void *)(((PBYTE)(_p)) + AF_UNIX_PKT_OFFSETOF_DATA (_p)); \ }) -/* Character length of pipe name, excluding trailing NUL. */ -#define CYGWIN_PIPE_SOCKET_NAME_LEN 47 - GUID __cygwin_socket_guid = { .Data1 = 0xefc1714d, .Data2 = 0x7b19, @@ -973,7 +970,7 @@ fhandler_socket_unix::dup (fhandler_base *child, int flags) things to do: - Set the peer pipe handle if successful - - Send own sun_path to peer if successful TODO + - Send own sun_path to peer if successful - Set connect_state - Set so_error for later call to select */
[newlib-cygwin] Cygwin: AF_UNIX: some pipe errors may have multiple status codes
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=27a63d4ef2d062d318330682e01f88b4a7298f97 commit 27a63d4ef2d062d318330682e01f88b4a7298f97 Author: Corinna VinschenDate: Wed Mar 7 16:12:55 2018 +0100 Cygwin: AF_UNIX: some pipe errors may have multiple status codes Depending on the exact circumstances, some erros are indicated by different status codes. Add helper macros to handle them together. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler_socket_unix.cc | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 27ac958..099000d 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -131,6 +131,29 @@ GUID __cygwin_socket_guid = { .Data4 = { 0xba, 0xb3, 0xc5, 0xb1, 0xf9, 0x2c, 0xb8, 0x8c } }; +/* Some error conditions on pipes have multiple status codes, unfortunately. */ +#define STATUS_PIPE_NO_INSTANCE_AVAILABLE(status) \ + ({ NTSTATUS _s = (status); \ + _s == STATUS_INSTANCE_NOT_AVAILABLE \ + || _s == STATUS_PIPE_NOT_AVAILABLE \ + || _s == STATUS_PIPE_BUSY; }) + +#define STATUS_PIPE_IS_CLOSING(status) \ + ({ NTSTATUS _s = (status); \ + _s == STATUS_PIPE_CLOSING \ + || _s == STATUS_PIPE_EMPTY; }) + +#define STATUS_PIPE_INVALID(status) \ + ({ NTSTATUS _s = (status); \ + _s == STATUS_INVALID_INFO_CLASS \ + || _s == STATUS_INVALID_PIPE_STATE \ + || _s == STATUS_INVALID_READ_MODE; }) + +#define STATUS_PIPE_MORE_DATA(status) \ + ({ NTSTATUS _s = (status); \ + _s == STATUS_BUFFER_OVERFLOW \ + || _s == STATUS_MORE_PROCESSING_REQUIRED; }) + sun_name_t::sun_name_t () { un_len = sizeof (sa_family_t); @@ -847,7 +870,7 @@ fhandler_socket_unix::connect_pipe (PUNICODE_STRING pipe_name) /* Try connecting first. If it doesn't work, wait for the pipe to become available. */ status = open_pipe (ph, pipe_name); - if (status == STATUS_PIPE_BUSY) + if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status)) return wait_pipe (pipe_name); if (!NT_SUCCESS (status)) { @@ -1026,7 +1049,7 @@ fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name) case STATUS_SUCCESS: { status = open_pipe (ph, pipe_name); - if (status == STATUS_PIPE_BUSY) + if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status)) { /* Another concurrent connect grabbed the pipe instance under our nose. Fix the timeout value and go waiting @@ -1057,7 +1080,7 @@ fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name) break; } } - while (status == STATUS_PIPE_BUSY); + while (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status)); out: PVOID param = InterlockedExchangePointer (_param, NULL); if (param)