1 /*
   2  * Copyright (c) 2001, 2013, 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 /*
  27  * This file contains implementations of NET_... functions. The NET_.. functions are
  28  * wrappers for common file- and socket functions plus provisions for non-blocking IO.
  29  *
  30  * (basically, the layers remember all  file descriptors waiting for a particular fd;
  31  *  all threads waiting on a certain fd can be woken up by sending them a signal; this
  32  *  is done e.g. when the fd is closed.)
  33  *
  34  * This was originally copied from the linux_close.c implementation.
  35  *
  36  * Side Note: This coding needs initialization. Under Linux this is done
  37  * automatically via __attribute((constructor)), on AIX this is done manually
  38  * (see aix_close_init).
  39  *
  40  */
  41 
  42 /*
  43    AIX needs a workaround for I/O cancellation, see:
  44    http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
  45    ...
  46    The close subroutine is blocked until all subroutines which use the file
  47    descriptor return to usr space. For example, when a thread is calling close
  48    and another thread is calling select with the same file descriptor, the
  49    close subroutine does not return until the select call returns.
  50    ...
  51 */
  52 
  53 #include <stdio.h>
  54 #include <stdlib.h>
  55 #include <signal.h>
  56 #include <pthread.h>
  57 #include <sys/types.h>
  58 #include <sys/socket.h>
  59 #include <sys/time.h>
  60 #include <sys/resource.h>
  61 #include <sys/uio.h>
  62 #include <unistd.h>
  63 #include <errno.h>

  64 #include <sys/poll.h>
  65 
  66 #include "jni.h"
  67 
  68 /*
  69  * Stack allocated by thread when doing blocking operation
  70  */
  71 typedef struct threadEntry {
  72     pthread_t thr;                      /* this thread */
  73     struct threadEntry *next;           /* next thread */
  74     int intr;                           /* interrupted */
  75 } threadEntry_t;
  76 
  77 /*
  78  * Heap allocated during initialized - one entry per fd
  79  */
  80 typedef struct {
  81     pthread_mutex_t lock;               /* fd lock */
  82     threadEntry_t *threads;             /* threads blocked on fd */
  83 } fdEntry_t;
  84 
  85 /*
  86  * Signal to unblock thread
  87  */
  88 static int sigWakeup = (SIGRTMAX - 1);
  89 
  90 /*
  91  * The fd table and the number of file descriptors
  92  */
  93 static fdEntry_t *fdTable = NULL;
  94 static int fdCount = 0;
  95 
  96 /*
  97  * Null signal handler
  98  */
  99 static void sig_wakeup(int sig) {
 100 }
 101 
 102 /*
 103  * Initialization routine (executed when library is loaded)
 104  * Allocate fd tables and sets up signal handler.
 105  *
 106  * On AIX we don't have __attribute((constructor)) so we need to initialize
 107  * manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c')
 108  */
 109 void aix_close_init() {
 110     struct rlimit nbr_files;
 111     sigset_t sigset;
 112     struct sigaction sa;
 113 
 114     /* Check already initialized */
 115     if (fdCount > 0 && fdTable != NULL) {
 116         return;
 117     }
 118 
 119     /*
 120      * Allocate table based on the maximum number of
 121      * file descriptors.
 122      */
 123     if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
 124         fprintf(stderr, "library initialization failed - "
 125                 "unable to get max # of allocated fds\n");
 126         abort();
 127     }
 128     fdCount = nbr_files.rlim_max;
 129     /*
 130      * We have a conceptual problem here, when the number of files is
 131      * unlimited. As a kind of workaround, we ensure the table is big
 132      * enough for handle even a large number of files. Since SAP itself
 133      * recommends a limit of 32000 files, we just use 64000 as 'infinity'.
 134      */
 135     if (nbr_files.rlim_max == RLIM_INFINITY) {
 136         fdCount = 64000;
 137     }
 138     fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
 139     if (fdTable == NULL) {
 140         fprintf(stderr, "library initialization failed - "
 141                 "unable to allocate file descriptor table - out of memory");
 142         abort();
 143     }
 144 
 145     {
 146         int i;
 147         for (i=0; i < fdCount; i++) {
 148             pthread_mutex_init(&fdTable[i].lock, NULL);
 149         }
 150     }
 151 
 152     /*
 153      * Setup the signal handler
 154      */
 155     sa.sa_handler = sig_wakeup;
 156     sa.sa_flags   = 0;
 157     sigemptyset(&sa.sa_mask);
 158     sigaction(sigWakeup, &sa, NULL);
 159 
 160     sigemptyset(&sigset);
 161     sigaddset(&sigset, sigWakeup);
 162     sigprocmask(SIG_UNBLOCK, &sigset, NULL);
 163 }
 164 
 165 /*
 166  * Return the fd table for this fd or NULL is fd out
 167  * of range.
 168  */
 169 static inline fdEntry_t *getFdEntry(int fd)
 170 {
 171     if (fd < 0 || fd >= fdCount) {
 172         return NULL;
 173     }
 174     return &fdTable[fd];
 175 }
 176 
 177 /*
 178  * Start a blocking operation :-
 179  *    Insert thread onto thread list for the fd.
 180  */
 181 static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
 182 {
 183     self->thr = pthread_self();
 184     self->intr = 0;
 185 
 186     pthread_mutex_lock(&(fdEntry->lock));
 187     {
 188         self->next = fdEntry->threads;
 189         fdEntry->threads = self;
 190     }
 191     pthread_mutex_unlock(&(fdEntry->lock));
 192 }
 193 
 194 /*
 195  * End a blocking operation :-
 196  *     Remove thread from thread list for the fd
 197  *     If fd has been interrupted then set errno to EBADF
 198  */
 199 static inline void endOp
 200     (fdEntry_t *fdEntry, threadEntry_t *self)
 201 {
 202     int orig_errno = errno;
 203     pthread_mutex_lock(&(fdEntry->lock));
 204     {
 205         threadEntry_t *curr, *prev=NULL;
 206         curr = fdEntry->threads;
 207         while (curr != NULL) {
 208             if (curr == self) {
 209                 if (curr->intr) {
 210                     orig_errno = EBADF;
 211                 }
 212                 if (prev == NULL) {
 213                     fdEntry->threads = curr->next;
 214                 } else {
 215                     prev->next = curr->next;
 216                 }
 217                 break;
 218             }
 219             prev = curr;
 220             curr = curr->next;
 221         }
 222     }
 223     pthread_mutex_unlock(&(fdEntry->lock));
 224     errno = orig_errno;
 225 }
 226 
 227 /*
 228  * Close or dup2 a file descriptor ensuring that all threads blocked on
 229  * the file descriptor are notified via a wakeup signal.
 230  *
 231  *      fd1 < 0    => close(fd2)
 232  *      fd1 >= 0   => dup2(fd1, fd2)
 233  *
 234  * Returns -1 with errno set if operation fails.
 235  */
 236 static int closefd(int fd1, int fd2) {
 237     int rv, orig_errno;
 238     fdEntry_t *fdEntry = getFdEntry(fd2);
 239     if (fdEntry == NULL) {
 240         errno = EBADF;
 241         return -1;
 242     }
 243 
 244     /*
 245      * Lock the fd to hold-off additional I/O on this fd.
 246      */
 247     pthread_mutex_lock(&(fdEntry->lock));
 248 
 249     {
 250         /* On fast machines we see that we enter dup2 before the
 251          * accepting thread had a chance to get and process the signal.
 252          * So in case we woke a thread up, give it some time to cope.
 253          * Also see https://bugs.openjdk.java.net/browse/JDK-8006395 */
 254         int num_woken = 0;
 255 
 256         /*
 257          * Send a wakeup signal to all threads blocked on this
 258          * file descriptor.
 259          */
 260         threadEntry_t *curr = fdEntry->threads;
 261         while (curr != NULL) {
 262             curr->intr = 1;
 263             pthread_kill( curr->thr, sigWakeup );
 264             num_woken ++;
 265             curr = curr->next;
 266         }
 267 
 268         if (num_woken > 0) {
 269           usleep(num_woken * 50);
 270         }
 271 
 272         /*
 273          * And close/dup the file descriptor
 274          * (restart if interrupted by signal)
 275          */
 276         do {
 277             if (fd1 < 0) {
 278                 rv = close(fd2);
 279             } else {
 280                 rv = dup2(fd1, fd2);
 281             }
 282         } while (rv == -1 && errno == EINTR);
 283     }
 284 
 285     /*
 286      * Unlock without destroying errno
 287      */
 288     orig_errno = errno;
 289     pthread_mutex_unlock(&(fdEntry->lock));
 290     errno = orig_errno;
 291 
 292     return rv;
 293 }
 294 
 295 /*
 296  * Wrapper for dup2 - same semantics as dup2 system call except
 297  * that any threads blocked in an I/O system call on fd2 will be
 298  * preempted and return -1/EBADF;
 299  */
 300 int NET_Dup2(int fd, int fd2) {
 301     if (fd < 0) {
 302         errno = EBADF;
 303         return -1;
 304     }
 305     return closefd(fd, fd2);
 306 }
 307 
 308 /*
 309  * Wrapper for close - same semantics as close system call
 310  * except that any threads blocked in an I/O on fd will be
 311  * preempted and the I/O system call will return -1/EBADF.
 312  */
 313 int NET_SocketClose(int fd) {
 314     return closefd(-1, fd);
 315 }
 316 
 317 /************** Basic I/O operations here ***************/
 318 
 319 /*
 320  * Macro to perform a blocking IO operation. Restarts
 321  * automatically if interrupted by signal (other than
 322  * our wakeup signal)
 323  */
 324 #define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
 325     int ret;                                    \
 326     threadEntry_t self;                         \
 327     fdEntry_t *fdEntry = getFdEntry(FD);        \
 328     if (fdEntry == NULL) {                      \
 329         errno = EBADF;                          \
 330         return -1;                              \
 331     }                                           \
 332     do {                                        \
 333         startOp(fdEntry, &self);                \
 334         ret = FUNC;                             \
 335         endOp(fdEntry, &self);                  \
 336     } while (ret == -1 && errno == EINTR);      \
 337     return ret;                                 \
 338 }
 339 
 340 int NET_Read(int s, void* buf, size_t len) {
 341     BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
 342 }
 343 
 344 int NET_ReadV(int s, const struct iovec * vector, int count) {
 345     BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
 346 }
 347 
 348 int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
 349        struct sockaddr *from, int *fromlen) {
 350     socklen_t socklen = *fromlen;
 351     BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
 352     *fromlen = socklen;
 353 }
 354 
 355 int NET_Send(int s, void *msg, int len, unsigned int flags) {
 356     BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
 357 }
 358 
 359 int NET_WriteV(int s, const struct iovec * vector, int count) {
 360     BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
 361 }
 362 
 363 int NET_SendTo(int s, const void *msg, int len,  unsigned  int
 364        flags, const struct sockaddr *to, int tolen) {
 365     BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
 366 }
 367 
 368 int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
 369     socklen_t socklen = *addrlen;
 370     BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
 371     *addrlen = socklen;
 372 }
 373 
 374 int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
 375     BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
 376 }
 377 
 378 #ifndef USE_SELECT
 379 int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
 380     BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
 381 }
 382 #else
 383 int NET_Select(int s, fd_set *readfds, fd_set *writefds,
 384                fd_set *exceptfds, struct timeval *timeout) {
 385     BLOCKING_IO_RETURN_INT( s-1,
 386                             select(s, readfds, writefds, exceptfds, timeout) );
 387 }
 388 #endif
 389 
 390 /*
 391  * Wrapper for poll(s, timeout).
 392  * Auto restarts with adjusted timeout if interrupted by
 393  * signal other than our wakeup signal.
 394  */
 395 int NET_Timeout(JNIEnv *unused, int s, long timeout) {
 396     long prevtime = 0, newtime;
 397     struct timeval t;
 398     fdEntry_t *fdEntry = getFdEntry(s);
 399 
 400     /*
 401      * Check that fd hasn't been closed.
 402      */
 403     if (fdEntry == NULL) {
 404         errno = EBADF;
 405         return -1;
 406     }
 407 
 408     /*
 409      * Pick up current time as may need to adjust timeout
 410      */
 411     if (timeout > 0) {
 412         gettimeofday(&t, NULL);
 413         prevtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
 414     }
 415 
 416     for(;;) {
 417         struct pollfd pfd;
 418         int rv;
 419         threadEntry_t self;
 420 
 421         /*
 422          * Poll the fd. If interrupted by our wakeup signal
 423          * errno will be set to EBADF.
 424          */
 425         pfd.fd = s;
 426         pfd.events = POLLIN | POLLERR;
 427 
 428         startOp(fdEntry, &self);
 429         rv = poll(&pfd, 1, timeout);
 430         endOp(fdEntry, &self);
 431 
 432         /*
 433          * If interrupted then adjust timeout. If timeout
 434          * has expired return 0 (indicating timeout expired).
 435          */
 436         if (rv < 0 && errno == EINTR) {
 437             if (timeout > 0) {
 438                 gettimeofday(&t, NULL);
 439                 newtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
 440                 timeout -= newtime - prevtime;
 441                 if (timeout <= 0) {
 442                     return 0;
 443                 }
 444                 prevtime = newtime;
 445             }
 446         } else {
 447             return rv;
 448         }
 449 
 450     }
 451 }
--- EOF ---