Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <signal.h>
     29 #include <pthread.h>
     30 #include <sys/types.h>
     31 #include <sys/socket.h>
     32 #include <sys/time.h>
     33 #include <sys/resource.h>
     34 #include <sys/uio.h>
     35 #include <unistd.h>
     36 #include <errno.h>
     37 
     38 #include <sys/poll.h>
     39 
     40 
     41 #include "AsynchronousCloseMonitor.h"
     42 
     43 extern "C" {
     44 
     45 /*
     46  * Signal to unblock thread
     47  */
     48 static int sigWakeup = (__SIGRTMAX - 2);
     49 
     50 /*
     51  * Close or dup2 a file descriptor ensuring that all threads blocked on
     52  * the file descriptor are notified via a wakeup signal.
     53  *
     54  *      fd1 < 0    => close(fd2)
     55  *      fd1 >= 0   => dup2(fd1, fd2)
     56  *
     57  * Returns -1 with errno set if operation fails.
     58  */
     59 static int closefd(int fd1, int fd2) {
     60     int rv, orig_errno;
     61 
     62     AsynchronousCloseMonitor::signalBlockedThreads(fd2);
     63 
     64     /*
     65      * And close/dup the file descriptor
     66      * (restart if interrupted by signal)
     67      */
     68     do {
     69       if (fd1 < 0) {
     70         rv = close(fd2);
     71       } else {
     72         rv = dup2(fd1, fd2);
     73       }
     74     } while (rv == -1 && errno == EINTR);
     75     return rv;
     76 }
     77 
     78 /*
     79  * Wrapper for dup2 - same semantics as dup2 system call except
     80  * that any threads blocked in an I/O system call on fd2 will be
     81  * preempted and return -1/EBADF;
     82  */
     83 int NET_Dup2(int fd, int fd2) {
     84     if (fd < 0) {
     85         errno = EBADF;
     86         return -1;
     87     }
     88     return closefd(fd, fd2);
     89 }
     90 
     91 /*
     92  * Wrapper for close - same semantics as close system call
     93  * except that any threads blocked in an I/O on fd will be
     94  * preempted and the I/O system call will return -1/EBADF.
     95  */
     96 int NET_SocketClose(int fd) {
     97     return closefd(-1, fd);
     98 }
     99 
    100 /************** Basic I/O operations here ***************/
    101 
    102 /*
    103  * Macro to perform a blocking IO operation. Restarts
    104  * automatically if interrupted by signal (other than
    105  * our wakeup signal)
    106  */
    107 #define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
    108     int ret;                                    \
    109     int _syscallErrno; \
    110     do {                                        \
    111         bool _wasSignaled; \
    112         {                                       \
    113             AsynchronousCloseMonitor _monitor(FD); \
    114             ret = FUNC;                            \
    115             _syscallErrno = errno; \
    116             _wasSignaled = _monitor.wasSignaled(); \
    117         } \
    118         errno = _wasSignaled ? EBADF : _syscallErrno; \
    119     } while (ret == -1 && errno == EINTR);      \
    120     return ret;                                 \
    121 }
    122 
    123 
    124 int NET_Read(int s, void* buf, size_t len) {
    125     BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
    126 }
    127 
    128 int NET_ReadV(int s, const struct iovec * vector, int count) {
    129     BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
    130 }
    131 
    132 int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
    133        struct sockaddr *from, int *fromlen) {
    134     socklen_t socklen = *fromlen;
    135     BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
    136     *fromlen = socklen;
    137 }
    138 
    139 int NET_Send(int s, void *msg, int len, unsigned int flags) {
    140     BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
    141 }
    142 
    143 int NET_WriteV(int s, const struct iovec * vector, int count) {
    144     BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
    145 }
    146 
    147 int NET_SendTo(int s, const void *msg, int len,  unsigned  int
    148        flags, const struct sockaddr *to, int tolen) {
    149     BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
    150 }
    151 
    152 int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
    153     socklen_t socklen = *addrlen;
    154     BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
    155     *addrlen = socklen;
    156 }
    157 
    158 int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
    159     BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
    160 }
    161 
    162 #ifndef USE_SELECT
    163 int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
    164     BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
    165 }
    166 #else
    167 int NET_Select(int s, fd_set *readfds, fd_set *writefds,
    168                fd_set *exceptfds, struct timeval *timeout) {
    169     BLOCKING_IO_RETURN_INT( s-1,
    170                             select(s, readfds, writefds, exceptfds, timeout) );
    171 }
    172 #endif
    173 
    174 /*
    175  * Wrapper for poll(s, timeout).
    176  * Auto restarts with adjusted timeout if interrupted by
    177  * signal other than our wakeup signal.
    178  *
    179  * If s < 0, exits early rather than delegating to poll().
    180  * TODO: Investigate whether it'd be better to handle this
    181  * case at the caller so that this function is never called
    182  * for s < 0.
    183  */
    184 int NET_Timeout(int s, long timeout) {
    185     long prevtime = 0, newtime;
    186     struct timeval t;
    187 
    188     /*
    189      * b/27763633
    190      * Avoid blocking calls to poll() for invalid sockets, e.g. when
    191      * called from PlainSocketImpl_socketAccept with fd == -1.
    192      */
    193     if (s < 0) {
    194         errno = EBADF;
    195         return -1;
    196     }
    197 
    198     /*
    199      * Pick up current time as may need to adjust timeout
    200      */
    201     if (timeout > 0) {
    202         gettimeofday(&t, NULL);
    203         prevtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
    204     }
    205 
    206     for(;;) {
    207         struct pollfd pfd;
    208         int rv;
    209 
    210         /*
    211          * Poll the fd. If interrupted by our wakeup signal
    212          * errno will be set to EBADF.
    213          */
    214         pfd.fd = s;
    215         pfd.events = POLLIN | POLLERR;
    216 
    217         bool wasSignaled;
    218         int syscallErrno;
    219         {
    220           AsynchronousCloseMonitor monitor(s);
    221           rv = poll(&pfd, 1, timeout);
    222           syscallErrno = errno;
    223           wasSignaled = monitor.wasSignaled();
    224         }
    225         errno = wasSignaled ? EBADF : syscallErrno;
    226 
    227         /*
    228          * If interrupted then adjust timeout. If timeout
    229          * has expired return 0 (indicating timeout expired).
    230          */
    231         if (rv < 0 && errno == EINTR) {
    232             if (timeout > 0) {
    233                 gettimeofday(&t, NULL);
    234                 newtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
    235                 timeout -= newtime - prevtime;
    236                 if (timeout <= 0) {
    237                     return 0;
    238                 }
    239                 prevtime = newtime;
    240             }
    241         } else {
    242             return rv;
    243         }
    244 
    245     }
    246 }
    247 
    248 }
    249