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