--- IO-FDPass/FDPass.xs 2013/04/05 04:26:41 1.2 +++ IO-FDPass/FDPass.xs 2021/01/03 23:54:05 1.8 @@ -1,7 +1,3 @@ -/* GetCurrentProcessId is XP and up, which means in all supported versions */ -/* but older SDK's might need this */ -#define _WIN32_WINNT NTDDI_WINXP - #ifdef __sun #define _XOPEN_SOURCE 1 #define _XOPEN_SOURCE_EXTENDED 1 @@ -23,8 +19,7 @@ #include #include - #define ioctlsocket(a,b,c) ioctl (a, b, c) - #define _open_osfhandle(h,m) cygwin_attach_handle_to_fd ("/dev/pipe", -1, (HANDLE)h, 1, GENERIC_READ | GENERIC_WRITE) + #define _open_osfhandle(h,m) cygwin_attach_handle_to_fd ("/dev/tcp", -1, (HANDLE)h, 1, GENERIC_READ | GENERIC_WRITE) typedef int SOCKET; #else @@ -39,11 +34,11 @@ #include #ifndef CMSG_SPACE - # define CMSG_SPACE(len) (sizeof (cmsghdr) + len) + # define CMSG_SPACE(len) (sizeof (struct cmsghdr) + len) #endif #ifndef CMSG_LEN - # define CMSG_LEN(len) (sizeof (cmsghdr) + len) + # define CMSG_LEN(len) (sizeof (struct cmsghdr) + len) #endif #endif @@ -61,25 +56,27 @@ while (got != len) { int sze = wr - ? send ((SOCKET)fd, buf, len, 0) /* we assume send and recv are macros with arguments */ - : recv ((SOCKET)fd, buf, len, 0); /* to be on the safe side */ + ? send ((SOCKET)fd, buf, len - got, 0) /* we assume send and recv are macros with arguments */ + : recv ((SOCKET)fd, buf, len - got, 0); /* to be on the safe side */ - if (sze <= 0) + if (sze < 0) { if (errno == EAGAIN || errno == WSAEWOULDBLOCK) { - ioctlsocket (fd, FIONBIO, &nbio); + ioctl (fd, FIONBIO, (void *)&nbio); nbio = 1; } else break; } + else if (sze == 0) + break; else got += sze; } if (nbio) - ioctlsocket (fd, FIONBIO, &nbio); + ioctl (fd, FIONBIO, (void *)&nbio); return got == len; } @@ -90,24 +87,23 @@ { #if defined(WIN32) DWORD pid; - HANDLE target, h; + HANDLE hdl; + + pid = GetCurrentProcessId (); - /* seriously, there is no way to query whether a socket is non-blocking?? */ - if (!rw (0, socket, (char *)&pid, sizeof (pid))) + if (!rw (1, socket, (char *)&pid, sizeof (pid))) return 0; - target = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid); - if (!target) - croak ("AnyEvent::ProcessPool::fd_recv: OpenProcess failed"); - - if (!DuplicateHandle ((HANDLE)-1, (HANDLE)_get_osfhandle (fd), target, &h, 0, FALSE, DUPLICATE_SAME_ACCESS)) - croak ("AnyEvent::ProcessPool::fd_recv: DuplicateHandle failed"); - - CloseHandle (target); - - if (!rw (1, socket, (char *)&h , sizeof (h ))) + errno = EBADF; + if (!DuplicateHandle ((HANDLE)-1, (HANDLE)_get_osfhandle (fd), (HANDLE)-1, &hdl, 0, FALSE, DUPLICATE_SAME_ACCESS)) return 0; + if (!rw (1, socket, (char *)&hdl, sizeof (hdl))) + { + CloseHandle (hdl); + return 0; + } + return 1; #else @@ -150,16 +146,30 @@ fd_recv (int socket) { #if defined(WIN32) - DWORD pid = GetCurrentProcessId (); - HANDLE h; + DWORD pid; + HANDLE source, rhd, lhd; - if (!rw (1, socket, (char *)&pid, sizeof (pid))) + if (!rw (0, socket, (char *)&pid, sizeof (pid))) return -1; - if (!rw (0, socket, (char *)&h , sizeof (h ))) + if (!rw (0, socket, (char *)&rhd, sizeof (rhd))) return -1; - return _open_osfhandle ((intptr_t)h, 0); + source = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid); + errno = EACCES; + if (!source) + return -1; + + pid = DuplicateHandle (source, rhd, (HANDLE)-1, &lhd, + 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); + + CloseHandle (source); + + errno = EBADF; + if (!pid) + return -1; + + return _open_osfhandle ((intptr_t)lhd, 0); #else void *buf = malloc (CMSG_SPACE (sizeof (int))); @@ -181,27 +191,22 @@ msg.msg_controllen = CMSG_SPACE (sizeof (int)); if (recvmsg (socket, &msg, 0) <= 0) - return -1; + { + free (buf); + return -1; + } int fd = -1; - errno = EDOM; - if ( - data == 0 -#if __OpenBSD__ - && msg.msg_controllen >= CMSG_LEN (sizeof (int)) /* work around a bug in at least openbsd 4.5 and 4.8 */ -#else - && msg.msg_controllen >= CMSG_SPACE (sizeof (int)) -#endif - ) { - struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); + struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); - if (cmsg->cmsg_level == SOL_SOCKET - && cmsg->cmsg_type == SCM_RIGHTS - && cmsg->cmsg_len >= CMSG_LEN (sizeof (int))) - fd = *(int *)CMSG_DATA (cmsg); - } + if (data == 0 + && cmsg + && cmsg->cmsg_level == SOL_SOCKET + && cmsg->cmsg_type == SCM_RIGHTS + && cmsg->cmsg_len >= CMSG_LEN (sizeof (int))) + fd = *(int *)CMSG_DATA (cmsg); free (buf);