From a4e5706eb2e207ee891bc1dec7488ac6d3a14d48 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 6 May 2011 10:56:37 +0000 Subject: [PATCH] * fhandler.h (fhandler_socket::read): Declare. (fhandler_socket::write): Declare. * fhandler_procsys.cc (fhandler_procsys::read): Add FIXME comment. (fhandler_procsys::write): Ditto. * fhandler_socket.cc (fhandler_socket::read): New method. (fhandler_socket::write): New method. * syscalls.cc: Rearrange order of read/write functions. (read): Call fhandler read method directly instead of just readv. (readv): Remove EINTR loop. This is done in all affected fhandler's now. (write): Call fhandler write method directly instead of just writev. Fix debug output. --- winsup/cygwin/ChangeLog | 15 +++ winsup/cygwin/fhandler.h | 2 + winsup/cygwin/fhandler_procsys.cc | 2 + winsup/cygwin/fhandler_socket.cc | 16 +++ winsup/cygwin/syscalls.cc | 174 +++++++++++++++++++----------- 5 files changed, 145 insertions(+), 64 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 7ef8f0101..ba024a10e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2011-05-06 Corinna Vinschen + + * fhandler.h (fhandler_socket::read): Declare. + (fhandler_socket::write): Declare. + * fhandler_procsys.cc (fhandler_procsys::read): Add FIXME comment. + (fhandler_procsys::write): Ditto. + * fhandler_socket.cc (fhandler_socket::read): New method. + (fhandler_socket::write): New method. + * syscalls.cc: Rearrange order of read/write functions. + (read): Call fhandler read method directly instead of just readv. + (readv): Remove EINTR loop. This is done in all affected fhandler's + now. + (write): Call fhandler write method directly instead of just writev. + Fix debug output. + 2011-05-05 Christopher Faylor * cygheap.cc (cygheap::close_ctty): Close ctty via close_with_arch(). diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 6ceaff33a..2dcbd9d8f 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -524,12 +524,14 @@ 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); + void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); 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 __stdcall write (const void *ptr, size_t len); 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, diff --git a/winsup/cygwin/fhandler_procsys.cc b/winsup/cygwin/fhandler_procsys.cc index dc73be56c..53d68cf77 100644 --- a/winsup/cygwin/fhandler_procsys.cc +++ b/winsup/cygwin/fhandler_procsys.cc @@ -398,6 +398,7 @@ fhandler_procsys::read (void *ptr, size_t& len) IO_STATUS_BLOCK io; LARGE_INTEGER off = { QuadPart:0LL }; + /* FIXME: Implement nonblocking I/O, interruptibility and cancelability. */ status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, ptr, len, &off, NULL); if (!NT_SUCCESS (status)) @@ -412,6 +413,7 @@ fhandler_procsys::read (void *ptr, size_t& len) ssize_t __stdcall fhandler_procsys::write (const void *ptr, size_t len) { + /* FIXME: Implement nonblocking I/O, interruptibility and cancelability. */ return fhandler_base::raw_write (ptr, len); } diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 1151f89fe..d97dc4f55 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -1316,6 +1316,14 @@ fhandler_socket::getpeername (struct sockaddr *name, int *namelen) return res; } +void __stdcall +fhandler_socket::read (void *in_ptr, size_t& len) +{ + WSABUF wsabuf = { len, (char *) in_ptr }; + WSAMSG wsamsg = { NULL, 0, &wsabuf, 1, { 0, NULL }, 0 }; + len = recv_internal (&wsamsg); +} + int fhandler_socket::readv (const struct iovec *const iov, const int iovcnt, ssize_t tot) @@ -1530,6 +1538,14 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags) return ret; } +int +fhandler_socket::write (const void *ptr, size_t len) +{ + WSABUF wsabuf = { len, (char *) ptr }; + WSAMSG wsamsg = { NULL, 0, &wsabuf, 1, { 0, NULL }, 0 }; + return send_internal (&wsamsg, 0); +} + int fhandler_socket::writev (const struct iovec *const iov, const int iovcnt, ssize_t tot) diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index d122c8dc2..70eb8ea1f 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -898,65 +898,41 @@ getsid (pid_t pid) extern "C" ssize_t read (int fd, void *ptr, size_t len) { - const iovec iov = - { - iov_base: ptr, - iov_len: len - }; + pthread_testcancel (); - return readv (fd, &iov, 1); + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + + size_t res = (size_t) -1; + + cygheap_fdget cfd (fd); + if (cfd < 0) + goto done; + + if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY) + { + set_errno (EBADF); + goto done; + } + + /* Could block, so let user know we at least got here. */ + extern int sigcatchers; + syscall_printf ("read (%d, %p, %d) %sblocking, sigcatchers %d", + fd, ptr, len, cfd->is_nonblocking () ? "non" : "", + sigcatchers); + + cfd->read (ptr, res = len); + +done: + syscall_printf ("%d = read (%d, %p, %d), errno %d", res, fd, ptr, len, + get_errno ()); + MALLOC_CHECK; + return (ssize_t) res; } EXPORT_ALIAS (read, _read) -extern "C" ssize_t -pread (int fd, void *ptr, size_t len, _off64_t off) -{ - pthread_testcancel (); - - ssize_t res; - cygheap_fdget cfd (fd); - if (cfd < 0) - res = -1; - else - res = cfd->pread (ptr, len, off); - - syscall_printf ("%d = pread (%d, %p, %d, %d), errno %d", - res, fd, ptr, len, off, get_errno ()); - return res; -} - -extern "C" ssize_t -pwrite (int fd, void *ptr, size_t len, _off64_t off) -{ - pthread_testcancel (); - - ssize_t res; - cygheap_fdget cfd (fd); - if (cfd < 0) - res = -1; - else - res = cfd->pwrite (ptr, len, off); - - syscall_printf ("%d = pwrite (%d, %p, %d, %d), errno %d", - res, fd, ptr, len, off, get_errno ()); - return res; -} - -extern "C" ssize_t -write (int fd, const void *ptr, size_t len) -{ - const struct iovec iov = - { - iov_base: (void *) ptr, // const_cast - iov_len: len - }; - - return writev (fd, &iov, 1); -} - -EXPORT_ALIAS (write, _write) - extern "C" ssize_t readv (int fd, const struct iovec *const iov, const int iovcnt) { @@ -967,7 +943,6 @@ readv (int fd, const struct iovec *const iov, const int iovcnt) return -1; ssize_t res = -1; - const int e = get_errno (); const ssize_t tot = check_iovec_for_read (iov, iovcnt); cygheap_fdget cfd (fd); @@ -992,13 +967,7 @@ readv (int fd, const struct iovec *const iov, const int iovcnt) fd, iov, iovcnt, cfd->is_nonblocking () ? "non" : "", sigcatchers); - while (1) - { - res = cfd->readv (iov, iovcnt, tot); - if (res >= 0 || get_errno () != EINTR || !_my_tls.call_signal_handler ()) - break; - set_errno (e); - } + res = cfd->readv (iov, iovcnt, tot); done: syscall_printf ("%d = readv (%d, %p, %d), errno %d", res, fd, iov, iovcnt, @@ -1007,6 +976,66 @@ done: return res; } +extern "C" ssize_t +pread (int fd, void *ptr, size_t len, _off64_t off) +{ + pthread_testcancel (); + + ssize_t res; + cygheap_fdget cfd (fd); + if (cfd < 0) + res = -1; + else + res = cfd->pread (ptr, len, off); + + syscall_printf ("%d = pread (%d, %p, %d, %d), errno %d", + res, fd, ptr, len, off, get_errno ()); + return res; +} + +extern "C" ssize_t +write (int fd, const void *ptr, size_t len) +{ + pthread_testcancel (); + + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + + int res = -1; + + cygheap_fdget cfd (fd); + if (cfd < 0) + goto done; + + if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY) + { + set_errno (EBADF); + goto done; + } + + /* Could block, so let user know we at least got here. */ + if (fd == 1 || fd == 2) + paranoid_printf ("write (%d, %p, %d)", fd, ptr, len); + else + syscall_printf ("write (%d, %p, %d)", fd, ptr, len); + + res = cfd->write (ptr, len); + +done: + if (fd == 1 || fd == 2) + paranoid_printf ("%d = write (%d, %p, %d), errno %d", + res, fd, ptr, len, get_errno ()); + else + syscall_printf ("%d = write (%d, %p, %d), errno %d", + res, fd, ptr, len, get_errno ()); + + MALLOC_CHECK; + return res; +} + +EXPORT_ALIAS (write, _write) + extern "C" ssize_t writev (const int fd, const struct iovec *const iov, const int iovcnt) { @@ -1045,16 +1074,33 @@ writev (const int fd, const struct iovec *const iov, const int iovcnt) done: if (fd == 1 || fd == 2) - paranoid_printf ("%d = write (%d, %p, %d), errno %d", + paranoid_printf ("%d = writev (%d, %p, %d), errno %d", res, fd, iov, iovcnt, get_errno ()); else - syscall_printf ("%d = write (%d, %p, %d), errno %d", + syscall_printf ("%d = writev (%d, %p, %d), errno %d", res, fd, iov, iovcnt, get_errno ()); MALLOC_CHECK; return res; } +extern "C" ssize_t +pwrite (int fd, void *ptr, size_t len, _off64_t off) +{ + pthread_testcancel (); + + ssize_t res; + cygheap_fdget cfd (fd); + if (cfd < 0) + res = -1; + else + res = cfd->pwrite (ptr, len, off); + + syscall_printf ("%d = pwrite (%d, %p, %d, %d), errno %d", + res, fd, ptr, len, off, get_errno ()); + return res; +} + /* _open */ /* newlib's fcntl.h defines _open as taking variable args so we must correspond. The third arg if it exists is: mode_t mode. */