tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

prio.c (6750B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "primpl.h"
      7 
      8 #include <string.h> /* for memset() */
      9 
     10 /************************************************************************/
     11 
     12 PRLock* _pr_flock_lock;
     13 PRCondVar* _pr_flock_cv;
     14 
     15 #ifdef WINCE
     16 /*
     17 * There are no stdin, stdout, stderr in Windows CE.  INVALID_HANDLE_VALUE
     18 * should cause all I/O functions on the handle to fail.
     19 */
     20 #  define STD_INPUT_HANDLE ((DWORD) - 10)
     21 #  define STD_OUTPUT_HANDLE ((DWORD) - 11)
     22 #  define STD_ERROR_HANDLE ((DWORD) - 12)
     23 
     24 static HANDLE GetStdHandle(DWORD nStdHandle) {
     25  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     26  return INVALID_HANDLE_VALUE;
     27 }
     28 #endif
     29 
     30 void _PR_InitIO(void) {
     31  const PRIOMethods* methods = PR_GetFileMethods();
     32 
     33  _PR_InitFdCache();
     34 
     35  _pr_flock_lock = PR_NewLock();
     36  _pr_flock_cv = PR_NewCondVar(_pr_flock_lock);
     37 
     38 #ifdef WIN32
     39  _pr_stdin = PR_AllocFileDesc((PROsfd)GetStdHandle(STD_INPUT_HANDLE), methods);
     40  _pr_stdout =
     41      PR_AllocFileDesc((PROsfd)GetStdHandle(STD_OUTPUT_HANDLE), methods);
     42  _pr_stderr =
     43      PR_AllocFileDesc((PROsfd)GetStdHandle(STD_ERROR_HANDLE), methods);
     44 #  ifdef WINNT
     45  _pr_stdin->secret->md.sync_file_io = PR_TRUE;
     46  _pr_stdout->secret->md.sync_file_io = PR_TRUE;
     47  _pr_stderr->secret->md.sync_file_io = PR_TRUE;
     48 #  endif
     49 #else
     50  _pr_stdin = PR_AllocFileDesc(0, methods);
     51  _pr_stdout = PR_AllocFileDesc(1, methods);
     52  _pr_stderr = PR_AllocFileDesc(2, methods);
     53 #endif
     54  _PR_MD_INIT_FD_INHERITABLE(_pr_stdin, PR_TRUE);
     55  _PR_MD_INIT_FD_INHERITABLE(_pr_stdout, PR_TRUE);
     56  _PR_MD_INIT_FD_INHERITABLE(_pr_stderr, PR_TRUE);
     57 
     58  _PR_MD_INIT_IO();
     59 }
     60 
     61 void _PR_CleanupIO(void) {
     62  PR_FreeFileDesc(_pr_stdin);
     63  _pr_stdin = NULL;
     64  PR_FreeFileDesc(_pr_stdout);
     65  _pr_stdout = NULL;
     66  PR_FreeFileDesc(_pr_stderr);
     67  _pr_stderr = NULL;
     68 
     69  if (_pr_flock_cv) {
     70    PR_DestroyCondVar(_pr_flock_cv);
     71    _pr_flock_cv = NULL;
     72  }
     73  if (_pr_flock_lock) {
     74    PR_DestroyLock(_pr_flock_lock);
     75    _pr_flock_lock = NULL;
     76  }
     77 
     78  _PR_CleanupFdCache();
     79 }
     80 
     81 PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd) {
     82  PRFileDesc* result = NULL;
     83  PR_ASSERT((int)osfd >= PR_StandardInput && osfd <= PR_StandardError);
     84 
     85  if (!_pr_initialized) {
     86    _PR_ImplicitInitialization();
     87  }
     88 
     89  switch (osfd) {
     90    case PR_StandardInput:
     91      result = _pr_stdin;
     92      break;
     93    case PR_StandardOutput:
     94      result = _pr_stdout;
     95      break;
     96    case PR_StandardError:
     97      result = _pr_stderr;
     98      break;
     99    default:
    100      (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    101  }
    102  return result;
    103 }
    104 
    105 PR_IMPLEMENT(PRFileDesc*)
    106 PR_AllocFileDesc(PROsfd osfd, const PRIOMethods* methods) {
    107  PRFileDesc* fd;
    108 
    109 #ifdef XP_UNIX
    110  /*
    111   * Assert that the file descriptor is small enough to fit in the
    112   * fd_set passed to select
    113   */
    114  PR_ASSERT(osfd < FD_SETSIZE);
    115 #endif
    116  fd = _PR_Getfd();
    117  if (fd) {
    118    /* Initialize the members of PRFileDesc and PRFilePrivate */
    119    fd->methods = methods;
    120    fd->secret->state = _PR_FILEDESC_OPEN;
    121    fd->secret->md.osfd = osfd;
    122 #if defined(_WIN64)
    123    fd->secret->alreadyConnected = PR_FALSE;
    124    fd->secret->overlappedActive = PR_FALSE;
    125 #endif
    126    _PR_MD_INIT_FILEDESC(fd);
    127  } else {
    128    PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    129  }
    130 
    131  return fd;
    132 }
    133 
    134 PR_IMPLEMENT(void) PR_FreeFileDesc(PRFileDesc* fd) {
    135  PR_ASSERT(fd);
    136  _PR_Putfd(fd);
    137 }
    138 
    139 #if defined(_WIN64) && defined(WIN95)
    140 
    141 PRFileDescList* _fd_waiting_for_overlapped_done = NULL;
    142 PRLock* _fd_waiting_for_overlapped_done_lock = NULL;
    143 
    144 void CheckOverlappedPendingSocketsAreDone() {
    145  if (!_fd_waiting_for_overlapped_done_lock ||
    146      !_fd_waiting_for_overlapped_done) {
    147    return;
    148  }
    149 
    150  PR_Lock(_fd_waiting_for_overlapped_done_lock);
    151 
    152  PRFileDescList* cur = _fd_waiting_for_overlapped_done;
    153  PRFileDescList* previous = NULL;
    154  while (cur) {
    155    PR_ASSERT(cur->fd->secret->overlappedActive);
    156    PRFileDesc* fd = cur->fd;
    157    DWORD rvSent;
    158    if (GetOverlappedResult((HANDLE)fd->secret->md.osfd, &fd->secret->ol,
    159                            &rvSent, FALSE) == TRUE) {
    160      fd->secret->overlappedActive = PR_FALSE;
    161      PR_LOG(_pr_io_lm, PR_LOG_MIN,
    162             ("CheckOverlappedPendingSocketsAreDone GetOverlappedResult "
    163              "succeeded\n"));
    164    } else {
    165      DWORD err = WSAGetLastError();
    166      PR_LOG(_pr_io_lm, PR_LOG_MIN,
    167             ("CheckOverlappedPendingSocketsAreDone GetOverlappedResult failed "
    168              "%d\n",
    169              err));
    170      if (err != ERROR_IO_INCOMPLETE) {
    171        fd->secret->overlappedActive = PR_FALSE;
    172      }
    173    }
    174 
    175    if (!fd->secret->overlappedActive) {
    176      _PR_MD_CLOSE_SOCKET(fd->secret->md.osfd);
    177      fd->secret->state = _PR_FILEDESC_CLOSED;
    178 #  ifdef _PR_HAVE_PEEK_BUFFER
    179      if (fd->secret->peekBuffer) {
    180        PR_ASSERT(fd->secret->peekBufSize > 0);
    181        PR_DELETE(fd->secret->peekBuffer);
    182        fd->secret->peekBufSize = 0;
    183        fd->secret->peekBytes = 0;
    184      }
    185 #  endif
    186 
    187      PR_FreeFileDesc(fd);
    188 
    189      if (previous) {
    190        previous->next = cur->next;
    191      } else {
    192        _fd_waiting_for_overlapped_done = cur->next;
    193      }
    194      PRFileDescList* del = cur;
    195      cur = cur->next;
    196      PR_Free(del);
    197    } else {
    198      previous = cur;
    199      cur = cur->next;
    200    }
    201  }
    202 
    203  PR_Unlock(_fd_waiting_for_overlapped_done_lock);
    204 }
    205 #endif
    206 
    207 /*
    208 ** Wait for some i/o to finish on one or more more poll descriptors.
    209 */
    210 PR_IMPLEMENT(PRInt32)
    211 PR_Poll(PRPollDesc* pds, PRIntn npds, PRIntervalTime timeout) {
    212 #if defined(_WIN64) && defined(WIN95)
    213  // For each iteration check if TFO overlapped IOs are down.
    214  CheckOverlappedPendingSocketsAreDone();
    215 #endif
    216 
    217  return (_PR_MD_PR_POLL(pds, npds, timeout));
    218 }
    219 
    220 /*
    221 ** Set the inheritance attribute of a file descriptor.
    222 */
    223 PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(PRFileDesc* fd, PRBool inheritable) {
    224 #if defined(XP_UNIX) || defined(WIN32)
    225  /*
    226   * Only a non-layered, NSPR file descriptor can be inherited
    227   * by a child process.
    228   */
    229  if (fd->identity != PR_NSPR_IO_LAYER) {
    230    PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    231    return PR_FAILURE;
    232  }
    233  if (fd->secret->inheritable != inheritable) {
    234    if (_PR_MD_SET_FD_INHERITABLE(fd, inheritable) == PR_FAILURE) {
    235      return PR_FAILURE;
    236    }
    237    fd->secret->inheritable = inheritable;
    238  }
    239  return PR_SUCCESS;
    240 #else
    241  PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    242  return PR_FAILURE;
    243 #endif
    244 }
    245 
    246 /*
    247 ** This function only has a useful implementation in the debug build of
    248 ** the pthreads version.
    249 */
    250 PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc* debug_out, const char* msg) {
    251  /* do nothing */
    252 } /* PT_FPrintStats */