LCOV - code coverage report
Current view: top level - nsprpub/pr/src/misc - prinit.c (source / functions) Hit Total Coverage
Test: output.info Lines: 70 238 29.4 %
Date: 2017-07-14 16:53:18 Functions: 3 5 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include <ctype.h>
       8             : #include <string.h>
       9             : 
      10             : PRLogModuleInfo *_pr_clock_lm;
      11             : PRLogModuleInfo *_pr_cmon_lm;
      12             : PRLogModuleInfo *_pr_io_lm;
      13             : PRLogModuleInfo *_pr_cvar_lm;
      14             : PRLogModuleInfo *_pr_mon_lm;
      15             : PRLogModuleInfo *_pr_linker_lm;
      16             : PRLogModuleInfo *_pr_sched_lm;
      17             : PRLogModuleInfo *_pr_thread_lm;
      18             : PRLogModuleInfo *_pr_gc_lm;
      19             : PRLogModuleInfo *_pr_shm_lm;
      20             : PRLogModuleInfo *_pr_shma_lm;
      21             : 
      22             : PRFileDesc *_pr_stdin;
      23             : PRFileDesc *_pr_stdout;
      24             : PRFileDesc *_pr_stderr;
      25             : 
      26             : #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
      27             : 
      28             : PRCList _pr_active_local_threadQ =
      29             :                         PR_INIT_STATIC_CLIST(&_pr_active_local_threadQ);
      30             : PRCList _pr_active_global_threadQ =
      31             :                         PR_INIT_STATIC_CLIST(&_pr_active_global_threadQ);
      32             : 
      33             : _MDLock  _pr_cpuLock;           /* lock for the CPU Q */
      34             : PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ);
      35             : 
      36             : PRUint32 _pr_utid;
      37             : 
      38             : PRInt32 _pr_userActive;
      39             : PRInt32 _pr_systemActive;
      40             : PRUintn _pr_maxPTDs;
      41             : 
      42             : #ifdef _PR_LOCAL_THREADS_ONLY
      43             : 
      44             : struct _PRCPU   *_pr_currentCPU;
      45             : PRThread        *_pr_currentThread;
      46             : PRThread        *_pr_lastThread;
      47             : PRInt32         _pr_intsOff;
      48             : 
      49             : #endif /* _PR_LOCAL_THREADS_ONLY */
      50             : 
      51             : /* Lock protecting all "termination" condition variables of all threads */
      52             : PRLock *_pr_terminationCVLock;
      53             : 
      54             : #endif /* !defined(_PR_PTHREADS) */
      55             : 
      56             : PRLock *_pr_sleeplock;  /* used in PR_Sleep(), classic and pthreads */
      57             : 
      58             : static void _PR_InitCallOnce(void);
      59             : 
      60             : PRBool _pr_initialized = PR_FALSE;
      61             : 
      62             : 
      63             : PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
      64             : {
      65             :     /*
      66             :     ** This is the secret handshake algorithm.
      67             :     **
      68             :     ** This release has a simple version compatibility
      69             :     ** check algorithm.  This release is not backward
      70             :     ** compatible with previous major releases.  It is
      71             :     ** not compatible with future major, minor, or
      72             :     ** patch releases.
      73             :     */
      74           0 :     int vmajor = 0, vminor = 0, vpatch = 0;
      75           0 :     const char *ptr = importedVersion;
      76             : 
      77           0 :     while (isdigit(*ptr)) {
      78           0 :         vmajor = 10 * vmajor + *ptr - '0';
      79           0 :         ptr++;
      80             :     }
      81           0 :     if (*ptr == '.') {
      82           0 :         ptr++;
      83           0 :         while (isdigit(*ptr)) {
      84           0 :             vminor = 10 * vminor + *ptr - '0';
      85           0 :             ptr++;
      86             :         }
      87           0 :         if (*ptr == '.') {
      88           0 :             ptr++;
      89           0 :             while (isdigit(*ptr)) {
      90           0 :                 vpatch = 10 * vpatch + *ptr - '0';
      91           0 :                 ptr++;
      92             :             }
      93             :         }
      94             :     }
      95             : 
      96           0 :     if (vmajor != PR_VMAJOR) {
      97           0 :         return PR_FALSE;
      98             :     }
      99           0 :     if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) {
     100           0 :         return PR_FALSE;
     101             :     }
     102           0 :     if (vmajor == PR_VMAJOR && vminor == PR_VMINOR && vpatch > PR_VPATCH) {
     103           0 :         return PR_FALSE;
     104             :     }
     105           0 :     return PR_TRUE;
     106             : }  /* PR_VersionCheck */
     107             : 
     108             : PR_IMPLEMENT(const char*) PR_GetVersion(void)
     109             : {
     110           0 :     return PR_VERSION;
     111             : }
     112             : 
     113             : PR_IMPLEMENT(PRBool) PR_Initialized(void)
     114             : {
     115           0 :     return _pr_initialized;
     116             : }
     117             : 
     118             : PRInt32 _native_threads_only = 0;
     119             : 
     120             : #ifdef WINNT
     121             : static void _pr_SetNativeThreadsOnlyMode(void)
     122             : {
     123             :     HMODULE mainExe;
     124             :     PRBool *globalp;
     125             :     char *envp;
     126             : 
     127             :     mainExe = GetModuleHandle(NULL);
     128             :     PR_ASSERT(NULL != mainExe);
     129             :     globalp = (PRBool *) GetProcAddress(mainExe, "nspr_native_threads_only");
     130             :     if (globalp) {
     131             :         _native_threads_only = (*globalp != PR_FALSE);
     132             :     } else if (envp = getenv("NSPR_NATIVE_THREADS_ONLY")) {
     133             :         _native_threads_only = (atoi(envp) == 1);
     134             :     }
     135             : }
     136             : #endif
     137             : 
     138           3 : static void _PR_InitStuff(void)
     139             : {
     140             : 
     141           3 :     if (_pr_initialized) return;
     142           3 :     _pr_initialized = PR_TRUE;
     143             : #ifdef _PR_ZONE_ALLOCATOR
     144           3 :     _PR_InitZones();
     145             : #endif
     146             : #ifdef WINNT
     147             :     _pr_SetNativeThreadsOnlyMode();
     148             : #endif
     149             : 
     150             : 
     151           3 :     (void) PR_GetPageSize();
     152             : 
     153           3 :         _pr_clock_lm = PR_NewLogModule("clock");
     154           3 :         _pr_cmon_lm = PR_NewLogModule("cmon");
     155           3 :         _pr_io_lm = PR_NewLogModule("io");
     156           3 :         _pr_mon_lm = PR_NewLogModule("mon");
     157           3 :         _pr_linker_lm = PR_NewLogModule("linker");
     158           3 :         _pr_cvar_lm = PR_NewLogModule("cvar");
     159           3 :         _pr_sched_lm = PR_NewLogModule("sched");
     160           3 :         _pr_thread_lm = PR_NewLogModule("thread");
     161           3 :         _pr_gc_lm = PR_NewLogModule("gc");
     162           3 :         _pr_shm_lm = PR_NewLogModule("shm");
     163           3 :         _pr_shma_lm = PR_NewLogModule("shma");
     164             :       
     165             :     /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */ 
     166           3 :     _PR_MD_EARLY_INIT();
     167             : 
     168           3 :     _PR_InitLocks();
     169           3 :     _PR_InitAtomic();
     170           3 :     _PR_InitSegs();
     171           3 :     _PR_InitStacks();
     172           3 :         _PR_InitTPD();
     173           3 :     _PR_InitEnv();
     174           3 :     _PR_InitLayerCache();
     175           3 :     _PR_InitClock();
     176             : 
     177           3 :     _pr_sleeplock = PR_NewLock();
     178           3 :     PR_ASSERT(NULL != _pr_sleeplock);
     179             : 
     180           3 :     _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
     181             :     
     182             : #ifdef WIN16
     183             :         {
     184             :         PRInt32 top;   /* artificial top of stack, win16 */
     185             :     _pr_top_of_task_stack = (char *) &top;
     186             :         }
     187             : #endif    
     188             : 
     189             : #ifndef _PR_GLOBAL_THREADS_ONLY
     190           3 :         _PR_InitCPUs();
     191             : #endif
     192             : 
     193             : /*
     194             :  * XXX: call _PR_InitMem only on those platforms for which nspr implements
     195             :  *      malloc, for now.
     196             :  */
     197             : #ifdef _PR_OVERRIDE_MALLOC
     198             :     _PR_InitMem();
     199             : #endif
     200             : 
     201           3 :     _PR_InitCMon();
     202           3 :     _PR_InitIO();
     203           3 :     _PR_InitNet();
     204           3 :     _PR_InitTime();
     205           3 :     _PR_InitLog();
     206           3 :     _PR_InitLinker();
     207           3 :     _PR_InitCallOnce();
     208           3 :     _PR_InitDtoa();
     209           3 :     _PR_InitMW();
     210           3 :     _PR_InitRWLocks();
     211             : 
     212           3 :     nspr_InitializePRErrorTable();
     213             : 
     214           3 :     _PR_MD_FINAL_INIT();
     215             : }
     216             : 
     217           3 : void _PR_ImplicitInitialization(void)
     218             : {
     219           3 :         _PR_InitStuff();
     220             : 
     221             :     /* Enable interrupts */
     222             : #if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY)
     223             :     _PR_MD_START_INTERRUPTS();
     224             : #endif
     225             : 
     226           3 : }
     227             : 
     228             : PR_IMPLEMENT(void) PR_DisableClockInterrupts(void)
     229             : {
     230             : #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
     231             :         if (!_pr_initialized) {
     232             :                 _PR_InitStuff();
     233             :         } else {
     234             :         _PR_MD_DISABLE_CLOCK_INTERRUPTS();
     235             :         }
     236             : #endif
     237           0 : }
     238             : 
     239             : PR_IMPLEMENT(void) PR_EnableClockInterrupts(void)
     240             : {
     241             : #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
     242             :         if (!_pr_initialized) {
     243             :                 _PR_InitStuff();
     244             :         }
     245             :     _PR_MD_ENABLE_CLOCK_INTERRUPTS();
     246             : #endif
     247           0 : }
     248             : 
     249             : PR_IMPLEMENT(void) PR_BlockClockInterrupts(void)
     250             : {
     251             : #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
     252             :         _PR_MD_BLOCK_CLOCK_INTERRUPTS();
     253             : #endif
     254           0 : }
     255             : 
     256             : PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void)
     257             : {
     258             : #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
     259             :         _PR_MD_UNBLOCK_CLOCK_INTERRUPTS();
     260             : #endif
     261           0 : }
     262             : 
     263             : PR_IMPLEMENT(void) PR_Init(
     264             :     PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
     265             : {
     266           0 :     _PR_ImplicitInitialization();
     267           0 : }
     268             : 
     269             : PR_IMPLEMENT(PRIntn) PR_Initialize(
     270             :     PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs)
     271             : {
     272             :     PRIntn rv;
     273           0 :     _PR_ImplicitInitialization();
     274           0 :     rv = prmain(argc, argv);
     275           0 :         PR_Cleanup();
     276           0 :     return rv;
     277             : }  /* PR_Initialize */
     278             : 
     279             : /*
     280             :  *-----------------------------------------------------------------------
     281             :  *
     282             :  * _PR_CleanupBeforeExit --
     283             :  *
     284             :  *   Perform the cleanup work before exiting the process. 
     285             :  *   We first do the cleanup generic to all platforms.  Then
     286             :  *   we call _PR_MD_CLEANUP_BEFORE_EXIT(), where platform-dependent
     287             :  *   cleanup is done.  This function is used by PR_Cleanup().
     288             :  *
     289             :  * See also: PR_Cleanup().
     290             :  *
     291             :  *-----------------------------------------------------------------------
     292             :  */
     293             : #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
     294             :     /* see ptthread.c */
     295             : #else
     296             : static void
     297             : _PR_CleanupBeforeExit(void)
     298             : {
     299             : /* 
     300             : Do not make any calls here other than to destroy resources.  For example,
     301             : do not make any calls that eventually may end up in PR_Lock.  Because the
     302             : thread is destroyed, can not access current thread any more.
     303             : */
     304             :     _PR_CleanupTPD();
     305             :     if (_pr_terminationCVLock)
     306             :     /*
     307             :      * In light of the comment above, this looks real suspicious.
     308             :      * I'd go so far as to say it's just a problem waiting to happen.
     309             :      */
     310             :         PR_DestroyLock(_pr_terminationCVLock);
     311             : 
     312             :     _PR_MD_CLEANUP_BEFORE_EXIT();
     313             : }
     314             : #endif /* defined(_PR_PTHREADS) */
     315             : 
     316             : /*
     317             :  *----------------------------------------------------------------------
     318             :  *
     319             :  * PR_Cleanup --
     320             :  *
     321             :  *   Perform a graceful shutdown of the NSPR runtime.  PR_Cleanup() may
     322             :  *   only be called from the primordial thread, typically at the
     323             :  *   end of the main() function.  It returns when it has completed
     324             :  *   its platform-dependent duty and the process must not make any other
     325             :  *   NSPR library calls prior to exiting from main().
     326             :  *
     327             :  *   PR_Cleanup() first blocks the primordial thread until all the
     328             :  *   other user (non-system) threads, if any, have terminated.
     329             :  *   Then it performs cleanup in preparation for exiting the process.
     330             :  *   PR_Cleanup() does not exit the primordial thread (which would
     331             :  *   in turn exit the process).
     332             :  *   
     333             :  *   PR_Cleanup() only responds when it is called by the primordial
     334             :  *   thread. Calls by any other thread are silently ignored.
     335             :  *
     336             :  * See also: PR_ExitProcess()
     337             :  *
     338             :  *----------------------------------------------------------------------
     339             :  */
     340             : #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
     341             :     /* see ptthread.c */
     342             : #else
     343             : 
     344             : PR_IMPLEMENT(PRStatus) PR_Cleanup()
     345             : {
     346             :     PRThread *me = PR_GetCurrentThread();
     347             :     PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL));
     348             :     if ((NULL != me) && (me->flags & _PR_PRIMORDIAL))
     349             :     {
     350             :         PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
     351             : 
     352             :         /*
     353             :          * No more recycling of threads
     354             :          */
     355             :         _pr_recycleThreads = 0;
     356             : 
     357             :         /*
     358             :          * Wait for all other user (non-system/daemon) threads
     359             :          * to terminate.
     360             :          */
     361             :         PR_Lock(_pr_activeLock);
     362             :         while (_pr_userActive > _pr_primordialExitCount) {
     363             :             PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT);
     364             :         }
     365             :         if (me->flags & _PR_SYSTEM) {
     366             :             _pr_systemActive--;
     367             :         } else {
     368             :             _pr_userActive--;
     369             :         }
     370             :         PR_Unlock(_pr_activeLock);
     371             : 
     372             : #ifdef IRIX
     373             :                 _PR_MD_PRE_CLEANUP(me);
     374             :                 /*
     375             :                  * The primordial thread must now be running on the primordial cpu
     376             :                  */
     377             :         PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0));
     378             : #endif
     379             : 
     380             :         _PR_MD_EARLY_CLEANUP();
     381             : 
     382             :         _PR_CleanupMW();
     383             :         _PR_CleanupTime();
     384             :         _PR_CleanupDtoa();
     385             :         _PR_CleanupCallOnce();
     386             :                 _PR_ShutdownLinker();
     387             :         _PR_CleanupNet();
     388             :         _PR_CleanupIO();
     389             :         /* Release the primordial thread's private data, etc. */
     390             :         _PR_CleanupThread(me);
     391             : 
     392             :         _PR_MD_STOP_INTERRUPTS();
     393             : 
     394             :             PR_LOG(_pr_thread_lm, PR_LOG_MIN,
     395             :                     ("PR_Cleanup: clean up before destroying thread"));
     396             :             _PR_LogCleanup();
     397             : 
     398             :         /*
     399             :          * This part should look like the end of _PR_NativeRunThread
     400             :          * and _PR_UserRunThread.
     401             :          */
     402             :         if (_PR_IS_NATIVE_THREAD(me)) {
     403             :             _PR_MD_EXIT_THREAD(me);
     404             :             _PR_NativeDestroyThread(me);
     405             :         } else {
     406             :             _PR_UserDestroyThread(me);
     407             :             PR_DELETE(me->stack);
     408             :             PR_DELETE(me);
     409             :         }
     410             : 
     411             :         /*
     412             :          * XXX: We are freeing the heap memory here so that Purify won't
     413             :          * complain, but we should also free other kinds of resources
     414             :          * that are allocated by the _PR_InitXXX() functions.
     415             :          * Ideally, for each _PR_InitXXX(), there should be a corresponding
     416             :          * _PR_XXXCleanup() that we can call here.
     417             :          */
     418             : #ifdef WINNT
     419             :         _PR_CleanupCPUs();
     420             : #endif
     421             :         _PR_CleanupThreads();
     422             :         _PR_CleanupCMon();
     423             :         PR_DestroyLock(_pr_sleeplock);
     424             :         _pr_sleeplock = NULL;
     425             :         _PR_CleanupLayerCache();
     426             :         _PR_CleanupEnv();
     427             :         _PR_CleanupStacks();
     428             :         _PR_CleanupBeforeExit();
     429             :         _pr_initialized = PR_FALSE;
     430             :         return PR_SUCCESS;
     431             :     }
     432             :     return PR_FAILURE;
     433             : }
     434             : #endif /* defined(_PR_PTHREADS) */
     435             : 
     436             : /*
     437             :  *------------------------------------------------------------------------
     438             :  * PR_ProcessExit --
     439             :  * 
     440             :  *   Cause an immediate, nongraceful, forced termination of the process.
     441             :  *   It takes a PRIntn argument, which is the exit status code of the
     442             :  *   process.
     443             :  *   
     444             :  * See also: PR_Cleanup()
     445             :  *
     446             :  *------------------------------------------------------------------------
     447             :  */
     448             : 
     449             : #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
     450             :     /* see ptthread.c */
     451             : #else
     452             : PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
     453             : {
     454             :     _PR_MD_EXIT(status);
     455             : }
     456             : 
     457             : #endif /* defined(_PR_PTHREADS) */
     458             : 
     459             : PR_IMPLEMENT(PRProcessAttr *)
     460             : PR_NewProcessAttr(void)
     461             : {
     462             :     PRProcessAttr *attr;
     463             : 
     464           0 :     attr = PR_NEWZAP(PRProcessAttr);
     465           0 :     if (!attr) {
     466           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     467             :     }
     468           0 :     return attr;
     469             : }
     470             : 
     471             : PR_IMPLEMENT(void)
     472             : PR_ResetProcessAttr(PRProcessAttr *attr)
     473             : {
     474           0 :     PR_FREEIF(attr->currentDirectory);
     475           0 :     PR_FREEIF(attr->fdInheritBuffer);
     476           0 :     memset(attr, 0, sizeof(*attr));
     477           0 : }
     478             : 
     479             : PR_IMPLEMENT(void)
     480             : PR_DestroyProcessAttr(PRProcessAttr *attr)
     481             : {
     482           0 :     PR_FREEIF(attr->currentDirectory);
     483           0 :     PR_FREEIF(attr->fdInheritBuffer);
     484           0 :     PR_DELETE(attr);
     485           0 : }
     486             : 
     487             : PR_IMPLEMENT(void)
     488             : PR_ProcessAttrSetStdioRedirect(
     489             :     PRProcessAttr *attr,
     490             :     PRSpecialFD stdioFd,
     491             :     PRFileDesc *redirectFd)
     492             : {
     493           0 :     switch (stdioFd) {
     494             :         case PR_StandardInput:
     495           0 :             attr->stdinFd = redirectFd;
     496           0 :             break;
     497             :         case PR_StandardOutput:
     498           0 :             attr->stdoutFd = redirectFd;
     499           0 :             break;
     500             :         case PR_StandardError:
     501           0 :             attr->stderrFd = redirectFd;
     502           0 :             break;
     503             :         default:
     504           0 :             PR_ASSERT(0);
     505             :     }
     506           0 : }
     507             : 
     508             : /*
     509             :  * OBSOLETE
     510             :  */
     511             : PR_IMPLEMENT(void)
     512             : PR_SetStdioRedirect(
     513             :     PRProcessAttr *attr,
     514             :     PRSpecialFD stdioFd,
     515             :     PRFileDesc *redirectFd)
     516             : {
     517             : #if defined(DEBUG)
     518             :     static PRBool warn = PR_TRUE;
     519           0 :     if (warn) {
     520           0 :         warn = _PR_Obsolete("PR_SetStdioRedirect()",
     521             :                 "PR_ProcessAttrSetStdioRedirect()");
     522             :     }
     523             : #endif
     524           0 :     PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd);
     525           0 : }
     526             : 
     527             : PR_IMPLEMENT(PRStatus)
     528             : PR_ProcessAttrSetCurrentDirectory(
     529             :     PRProcessAttr *attr,
     530             :     const char *dir)
     531             : {
     532           0 :     PR_FREEIF(attr->currentDirectory);
     533           0 :     attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1);
     534           0 :     if (!attr->currentDirectory) {
     535           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     536           0 :         return PR_FAILURE;
     537             :     }
     538           0 :     strcpy(attr->currentDirectory, dir);
     539           0 :     return PR_SUCCESS;
     540             : }
     541             : 
     542             : PR_IMPLEMENT(PRStatus)
     543             : PR_ProcessAttrSetInheritableFD(
     544             :     PRProcessAttr *attr,
     545             :     PRFileDesc *fd,
     546             :     const char *name)
     547             : {
     548             :     /* We malloc the fd inherit buffer in multiples of this number. */
     549             : #define FD_INHERIT_BUFFER_INCR 128
     550             :     /* The length of "NSPR_INHERIT_FDS=" */
     551             : #define NSPR_INHERIT_FDS_STRLEN 17
     552             :     /* The length of osfd (PROsfd) printed in hexadecimal with 0x prefix */
     553             : #ifdef _WIN64
     554             : #define OSFD_STRLEN 18
     555             : #else
     556             : #define OSFD_STRLEN 10
     557             : #endif
     558             :     /* The length of fd type (PRDescType) printed in decimal */
     559             : #define FD_TYPE_STRLEN 1
     560             :     PRSize newSize;
     561             :     int remainder;
     562             :     char *newBuffer;
     563             :     int nwritten;
     564             :     char *cur;
     565             :     int freeSize;
     566             : 
     567           0 :     if (fd->identity != PR_NSPR_IO_LAYER) {
     568           0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     569           0 :         return PR_FAILURE;
     570             :     }
     571           0 :     if (fd->secret->inheritable == _PR_TRI_UNKNOWN) {
     572           0 :         _PR_MD_QUERY_FD_INHERITABLE(fd);
     573             :     }
     574           0 :     if (fd->secret->inheritable != _PR_TRI_TRUE) {
     575           0 :         PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
     576           0 :         return PR_FAILURE;
     577             :     }
     578             : 
     579             :     /*
     580             :      * We also need to account for the : separators and the
     581             :      * terminating null byte.
     582             :      */
     583           0 :     if (NULL == attr->fdInheritBuffer) {
     584             :         /* The first time, we print "NSPR_INHERIT_FDS=<name>:<type>:<val>" */
     585           0 :         newSize = NSPR_INHERIT_FDS_STRLEN + strlen(name)
     586             :                 + FD_TYPE_STRLEN + OSFD_STRLEN + 2 + 1;
     587             :     } else {
     588             :         /* At other times, we print ":<name>:<type>:<val>" */
     589           0 :         newSize = attr->fdInheritBufferUsed + strlen(name)
     590             :                 + FD_TYPE_STRLEN + OSFD_STRLEN + 3 + 1;
     591             :     }
     592           0 :     if (newSize > attr->fdInheritBufferSize) {
     593             :         /* Make newSize a multiple of FD_INHERIT_BUFFER_INCR */
     594           0 :         remainder = newSize % FD_INHERIT_BUFFER_INCR;
     595           0 :         if (remainder != 0) {
     596           0 :             newSize += (FD_INHERIT_BUFFER_INCR - remainder);
     597             :         }
     598           0 :         if (NULL == attr->fdInheritBuffer) {
     599           0 :             newBuffer = (char *) PR_MALLOC(newSize);
     600             :         } else {
     601           0 :             newBuffer = (char *) PR_REALLOC(attr->fdInheritBuffer, newSize);
     602             :         }
     603           0 :         if (NULL == newBuffer) {
     604           0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     605           0 :             return PR_FAILURE;
     606             :         }
     607           0 :         attr->fdInheritBuffer = newBuffer;
     608           0 :         attr->fdInheritBufferSize = newSize;
     609             :     }
     610           0 :     cur = attr->fdInheritBuffer + attr->fdInheritBufferUsed;
     611           0 :     freeSize = attr->fdInheritBufferSize - attr->fdInheritBufferUsed;
     612           0 :     if (0 == attr->fdInheritBufferUsed) {
     613           0 :         nwritten = PR_snprintf(cur, freeSize,
     614             :                 "NSPR_INHERIT_FDS=%s:%d:0x%" PR_PRIxOSFD,
     615           0 :                 name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
     616             :     } else {
     617           0 :         nwritten = PR_snprintf(cur, freeSize, ":%s:%d:0x%" PR_PRIxOSFD,
     618           0 :                 name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
     619             :     }
     620           0 :     attr->fdInheritBufferUsed += nwritten; 
     621           0 :     return PR_SUCCESS;
     622             : }
     623             : 
     624             : PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD(
     625             :     const char *name)
     626             : {
     627             :     PRFileDesc *fd;
     628             :     const char *envVar;
     629             :     const char *ptr;
     630           0 :     int len = strlen(name);
     631             :     PROsfd osfd;
     632             :     int nColons;
     633             :     PRIntn fileType;
     634             : 
     635           0 :     envVar = PR_GetEnv("NSPR_INHERIT_FDS");
     636           0 :     if (NULL == envVar || '\0' == envVar[0]) {
     637           0 :         PR_SetError(PR_UNKNOWN_ERROR, 0);
     638           0 :         return NULL;
     639             :     }
     640             : 
     641           0 :     ptr = envVar;
     642             :     while (1) {
     643           0 :         if ((ptr[len] == ':') && (strncmp(ptr, name, len) == 0)) {
     644           0 :             ptr += len + 1;
     645           0 :             if (PR_sscanf(ptr, "%d:0x%" PR_SCNxOSFD, &fileType, &osfd) != 2) {
     646           0 :                 PR_SetError(PR_UNKNOWN_ERROR, 0);
     647           0 :                 return NULL;
     648             :             }
     649           0 :             switch ((PRDescType)fileType) {
     650             :                 case PR_DESC_FILE:
     651           0 :                     fd = PR_ImportFile(osfd);
     652           0 :                     break;
     653             :                 case PR_DESC_PIPE:
     654           0 :                     fd = PR_ImportPipe(osfd);
     655           0 :                     break;
     656             :                 case PR_DESC_SOCKET_TCP:
     657           0 :                     fd = PR_ImportTCPSocket(osfd);
     658           0 :                     break;
     659             :                 case PR_DESC_SOCKET_UDP:
     660           0 :                     fd = PR_ImportUDPSocket(osfd);
     661           0 :                     break;
     662             :                 default:
     663           0 :                     PR_ASSERT(0);
     664           0 :                     PR_SetError(PR_UNKNOWN_ERROR, 0);
     665           0 :                     fd = NULL;
     666           0 :                     break;
     667             :             }
     668           0 :             if (fd) {
     669             :                 /*
     670             :                  * An inherited FD is inheritable by default.
     671             :                  * The child process needs to call PR_SetFDInheritable
     672             :                  * to make it non-inheritable if so desired.
     673             :                  */
     674           0 :                 fd->secret->inheritable = _PR_TRI_TRUE;
     675             :             }
     676           0 :             return fd;
     677             :         }
     678             :         /* Skip three colons */
     679           0 :         nColons = 0;
     680           0 :         while (*ptr) {
     681           0 :             if (*ptr == ':') {
     682           0 :                 if (++nColons == 3) {
     683           0 :                     break;
     684             :                 }
     685             :             }
     686           0 :             ptr++;
     687             :         }
     688           0 :         if (*ptr == '\0') {
     689           0 :             PR_SetError(PR_UNKNOWN_ERROR, 0);
     690           0 :             return NULL;
     691             :         }
     692           0 :         ptr++;
     693             :     }
     694             : }
     695             : 
     696             : PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
     697             :     const char *path,
     698             :     char *const *argv,
     699             :     char *const *envp,
     700             :     const PRProcessAttr *attr)
     701             : {
     702           0 :     return _PR_MD_CREATE_PROCESS(path, argv, envp, attr);
     703             : }  /* PR_CreateProcess */
     704             : 
     705             : PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached(
     706             :     const char *path,
     707             :     char *const *argv,
     708             :     char *const *envp,
     709             :     const PRProcessAttr *attr)
     710             : {
     711             :     PRProcess *process;
     712             :     PRStatus rv;
     713             : 
     714           0 :     process = PR_CreateProcess(path, argv, envp, attr);
     715           0 :     if (NULL == process) {
     716           0 :         return PR_FAILURE;
     717             :     }
     718           0 :     rv = PR_DetachProcess(process);
     719           0 :     PR_ASSERT(PR_SUCCESS == rv);
     720           0 :     if (rv == PR_FAILURE) {
     721           0 :         PR_DELETE(process);
     722           0 :         return PR_FAILURE;
     723             :     }
     724           0 :     return PR_SUCCESS;
     725             : }
     726             : 
     727             : PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process)
     728             : {
     729           0 :     return _PR_MD_DETACH_PROCESS(process);
     730             : }
     731             : 
     732             : PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode)
     733             : {
     734           0 :     return _PR_MD_WAIT_PROCESS(process, exitCode);
     735             : }  /* PR_WaitProcess */
     736             : 
     737             : PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process)
     738             : {
     739           0 :     return _PR_MD_KILL_PROCESS(process);
     740             : }
     741             : 
     742             : /*
     743             :  ********************************************************************
     744             :  *
     745             :  * Module initialization
     746             :  *
     747             :  ********************************************************************
     748             :  */
     749             : 
     750             : static struct {
     751             :     PRLock *ml;
     752             :     PRCondVar *cv;
     753             : } mod_init;
     754             : 
     755           3 : static void _PR_InitCallOnce(void) {
     756           3 :     mod_init.ml = PR_NewLock();
     757           3 :     PR_ASSERT(NULL != mod_init.ml);
     758           3 :     mod_init.cv = PR_NewCondVar(mod_init.ml);
     759           3 :     PR_ASSERT(NULL != mod_init.cv);
     760           3 : }
     761             : 
     762           0 : void _PR_CleanupCallOnce()
     763             : {
     764           0 :     PR_DestroyLock(mod_init.ml);
     765           0 :     mod_init.ml = NULL;
     766           0 :     PR_DestroyCondVar(mod_init.cv);
     767           0 :     mod_init.cv = NULL;
     768           0 : }
     769             : 
     770             : PR_IMPLEMENT(PRStatus) PR_CallOnce(
     771             :     PRCallOnceType *once,
     772             :     PRCallOnceFN    func)
     773             : {
     774        3760 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     775             : 
     776        3760 :     if (!once->initialized) {
     777          30 :         if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
     778          30 :             once->status = (*func)();
     779          30 :             PR_Lock(mod_init.ml);
     780          30 :             once->initialized = 1;
     781          30 :             PR_NotifyAllCondVar(mod_init.cv);
     782          30 :             PR_Unlock(mod_init.ml);
     783             :         } else {
     784           0 :             PR_Lock(mod_init.ml);
     785           0 :             while (!once->initialized) {
     786           0 :                 PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
     787             :             }
     788           0 :             PR_Unlock(mod_init.ml);
     789             :         }
     790             :     } else {
     791        3730 :         if (PR_SUCCESS != once->status) {
     792           0 :             PR_SetError(PR_CALL_ONCE_ERROR, 0);
     793             :         }
     794             :     }
     795        3760 :     return once->status;
     796             : }
     797             : 
     798             : PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
     799             :     PRCallOnceType      *once,
     800             :     PRCallOnceWithArgFN  func,
     801             :     void                *arg)
     802             : {
     803        1199 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     804             : 
     805        1199 :     if (!once->initialized) {
     806           5 :         if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
     807           5 :             once->status = (*func)(arg);
     808           5 :             PR_Lock(mod_init.ml);
     809           5 :             once->initialized = 1;
     810           5 :             PR_NotifyAllCondVar(mod_init.cv);
     811           5 :             PR_Unlock(mod_init.ml);
     812             :         } else {
     813           0 :             PR_Lock(mod_init.ml);
     814           0 :             while (!once->initialized) {
     815           0 :                 PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
     816             :             }
     817           0 :             PR_Unlock(mod_init.ml);
     818             :         }
     819             :     } else {
     820        1194 :         if (PR_SUCCESS != once->status) {
     821           0 :             PR_SetError(PR_CALL_ONCE_ERROR, 0);
     822             :         }
     823             :     }
     824        1199 :     return once->status;
     825             : }
     826             : 
     827           0 : PRBool _PR_Obsolete(const char *obsolete, const char *preferred)
     828             : {
     829             : #if defined(DEBUG)
     830           0 :     PR_fprintf(
     831           0 :         PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n",
     832             :         obsolete, (NULL == preferred) ? "something else" : preferred);
     833             : #endif
     834           0 :     return PR_FALSE;
     835             : }  /* _PR_Obsolete */
     836             : 
     837             : /* prinit.c */
     838             : 
     839             : 

Generated by: LCOV version 1.13