nsprpub/pr/src/misc/prinit.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 #include "primpl.h"
     7 #include <ctype.h>
     8 #include <string.h>
    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;
    22 PRFileDesc *_pr_stdin;
    23 PRFileDesc *_pr_stdout;
    24 PRFileDesc *_pr_stderr;
    26 #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
    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);
    33 _MDLock  _pr_cpuLock;           /* lock for the CPU Q */
    34 PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ);
    36 PRUint32 _pr_utid;
    38 PRInt32 _pr_userActive;
    39 PRInt32 _pr_systemActive;
    40 PRUintn _pr_maxPTDs;
    42 #ifdef _PR_LOCAL_THREADS_ONLY
    44 struct _PRCPU 	*_pr_currentCPU;
    45 PRThread 	*_pr_currentThread;
    46 PRThread 	*_pr_lastThread;
    47 PRInt32 	_pr_intsOff;
    49 #endif /* _PR_LOCAL_THREADS_ONLY */
    51 /* Lock protecting all "termination" condition variables of all threads */
    52 PRLock *_pr_terminationCVLock;
    54 #endif /* !defined(_PR_PTHREADS) */
    56 PRLock *_pr_sleeplock;  /* used in PR_Sleep(), classic and pthreads */
    58 static void _PR_InitCallOnce(void);
    60 PRBool _pr_initialized = PR_FALSE;
    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     int vmajor = 0, vminor = 0, vpatch = 0;
    75     const char *ptr = importedVersion;
    77     while (isdigit(*ptr)) {
    78         vmajor = 10 * vmajor + *ptr - '0';
    79         ptr++;
    80     }
    81     if (*ptr == '.') {
    82         ptr++;
    83         while (isdigit(*ptr)) {
    84             vminor = 10 * vminor + *ptr - '0';
    85             ptr++;
    86         }
    87         if (*ptr == '.') {
    88             ptr++;
    89             while (isdigit(*ptr)) {
    90                 vpatch = 10 * vpatch + *ptr - '0';
    91                 ptr++;
    92             }
    93         }
    94     }
    96     if (vmajor != PR_VMAJOR) {
    97         return PR_FALSE;
    98     }
    99     if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) {
   100         return PR_FALSE;
   101     }
   102     if (vmajor == PR_VMAJOR && vminor == PR_VMINOR && vpatch > PR_VPATCH) {
   103         return PR_FALSE;
   104     }
   105     return PR_TRUE;
   106 }  /* PR_VersionCheck */
   108 PR_IMPLEMENT(const char*) PR_GetVersion(void)
   109 {
   110     return PR_VERSION;
   111 }
   113 PR_IMPLEMENT(PRBool) PR_Initialized(void)
   114 {
   115     return _pr_initialized;
   116 }
   118 PRInt32 _native_threads_only = 0;
   120 #ifdef WINNT
   121 static void _pr_SetNativeThreadsOnlyMode(void)
   122 {
   123     HMODULE mainExe;
   124     PRBool *globalp;
   125     char *envp;
   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
   138 static void _PR_InitStuff(void)
   139 {
   141     if (_pr_initialized) return;
   142     _pr_initialized = PR_TRUE;
   143 #ifdef _PR_ZONE_ALLOCATOR
   144     _PR_InitZones();
   145 #endif
   146 #ifdef WINNT
   147     _pr_SetNativeThreadsOnlyMode();
   148 #endif
   151     (void) PR_GetPageSize();
   153 	_pr_clock_lm = PR_NewLogModule("clock");
   154 	_pr_cmon_lm = PR_NewLogModule("cmon");
   155 	_pr_io_lm = PR_NewLogModule("io");
   156 	_pr_mon_lm = PR_NewLogModule("mon");
   157 	_pr_linker_lm = PR_NewLogModule("linker");
   158 	_pr_cvar_lm = PR_NewLogModule("cvar");
   159 	_pr_sched_lm = PR_NewLogModule("sched");
   160 	_pr_thread_lm = PR_NewLogModule("thread");
   161 	_pr_gc_lm = PR_NewLogModule("gc");
   162 	_pr_shm_lm = PR_NewLogModule("shm");
   163 	_pr_shma_lm = PR_NewLogModule("shma");
   165     /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */ 
   166     _PR_MD_EARLY_INIT();
   168     _PR_InitLocks();
   169     _PR_InitAtomic();
   170     _PR_InitSegs();
   171     _PR_InitStacks();
   172 	_PR_InitTPD();
   173     _PR_InitEnv();
   174     _PR_InitLayerCache();
   175     _PR_InitClock();
   177     _pr_sleeplock = PR_NewLock();
   178     PR_ASSERT(NULL != _pr_sleeplock);
   180     _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
   182 #ifdef WIN16
   183 	{
   184 	PRInt32 top;   /* artificial top of stack, win16 */
   185     _pr_top_of_task_stack = (char *) &top;
   186 	}
   187 #endif    
   189 #ifndef _PR_GLOBAL_THREADS_ONLY
   190 	_PR_InitCPUs();
   191 #endif
   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
   201     _PR_InitCMon();
   202     _PR_InitIO();
   203     _PR_InitNet();
   204     _PR_InitTime();
   205     _PR_InitLog();
   206     _PR_InitLinker();
   207     _PR_InitCallOnce();
   208     _PR_InitDtoa();
   209     _PR_InitMW();
   210     _PR_InitRWLocks();
   212     nspr_InitializePRErrorTable();
   214     _PR_MD_FINAL_INIT();
   215 }
   217 void _PR_ImplicitInitialization(void)
   218 {
   219 	_PR_InitStuff();
   221     /* Enable interrupts */
   222 #if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY)
   223     _PR_MD_START_INTERRUPTS();
   224 #endif
   226 }
   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 }
   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 }
   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 }
   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 }
   263 PR_IMPLEMENT(void) PR_Init(
   264     PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
   265 {
   266     _PR_ImplicitInitialization();
   267 }
   269 PR_IMPLEMENT(PRIntn) PR_Initialize(
   270     PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs)
   271 {
   272     PRIntn rv;
   273     _PR_ImplicitInitialization();
   274     rv = prmain(argc, argv);
   275 	PR_Cleanup();
   276     return rv;
   277 }  /* PR_Initialize */
   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);
   312     _PR_MD_CLEANUP_BEFORE_EXIT();
   313 }
   314 #endif /* defined(_PR_PTHREADS) */
   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
   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"));
   352         /*
   353          * No more recycling of threads
   354          */
   355         _pr_recycleThreads = 0;
   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);
   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
   380         _PR_MD_EARLY_CLEANUP();
   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);
   392         _PR_MD_STOP_INTERRUPTS();
   394 	    PR_LOG(_pr_thread_lm, PR_LOG_MIN,
   395 	            ("PR_Cleanup: clean up before destroying thread"));
   396 	    _PR_LogCleanup();
   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         }
   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) */
   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  */
   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 }
   457 #endif /* defined(_PR_PTHREADS) */
   459 PR_IMPLEMENT(PRProcessAttr *)
   460 PR_NewProcessAttr(void)
   461 {
   462     PRProcessAttr *attr;
   464     attr = PR_NEWZAP(PRProcessAttr);
   465     if (!attr) {
   466         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   467     }
   468     return attr;
   469 }
   471 PR_IMPLEMENT(void)
   472 PR_ResetProcessAttr(PRProcessAttr *attr)
   473 {
   474     PR_FREEIF(attr->currentDirectory);
   475     PR_FREEIF(attr->fdInheritBuffer);
   476     memset(attr, 0, sizeof(*attr));
   477 }
   479 PR_IMPLEMENT(void)
   480 PR_DestroyProcessAttr(PRProcessAttr *attr)
   481 {
   482     PR_FREEIF(attr->currentDirectory);
   483     PR_FREEIF(attr->fdInheritBuffer);
   484     PR_DELETE(attr);
   485 }
   487 PR_IMPLEMENT(void)
   488 PR_ProcessAttrSetStdioRedirect(
   489     PRProcessAttr *attr,
   490     PRSpecialFD stdioFd,
   491     PRFileDesc *redirectFd)
   492 {
   493     switch (stdioFd) {
   494         case PR_StandardInput:
   495             attr->stdinFd = redirectFd;
   496             break;
   497         case PR_StandardOutput:
   498             attr->stdoutFd = redirectFd;
   499             break;
   500         case PR_StandardError:
   501             attr->stderrFd = redirectFd;
   502             break;
   503         default:
   504             PR_ASSERT(0);
   505     }
   506 }
   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     if (warn) {
   520         warn = _PR_Obsolete("PR_SetStdioRedirect()",
   521                 "PR_ProcessAttrSetStdioRedirect()");
   522     }
   523 #endif
   524     PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd);
   525 }
   527 PR_IMPLEMENT(PRStatus)
   528 PR_ProcessAttrSetCurrentDirectory(
   529     PRProcessAttr *attr,
   530     const char *dir)
   531 {
   532     PR_FREEIF(attr->currentDirectory);
   533     attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1);
   534     if (!attr->currentDirectory) {
   535         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   536         return PR_FAILURE;
   537     }
   538     strcpy(attr->currentDirectory, dir);
   539     return PR_SUCCESS;
   540 }
   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;
   567     if (fd->identity != PR_NSPR_IO_LAYER) {
   568         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   569         return PR_FAILURE;
   570     }
   571     if (fd->secret->inheritable == _PR_TRI_UNKNOWN) {
   572         _PR_MD_QUERY_FD_INHERITABLE(fd);
   573     }
   574     if (fd->secret->inheritable != _PR_TRI_TRUE) {
   575         PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
   576         return PR_FAILURE;
   577     }
   579     /*
   580      * We also need to account for the : separators and the
   581      * terminating null byte.
   582      */
   583     if (NULL == attr->fdInheritBuffer) {
   584         /* The first time, we print "NSPR_INHERIT_FDS=<name>:<type>:<val>" */
   585         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         newSize = attr->fdInheritBufferUsed + strlen(name)
   590                 + FD_TYPE_STRLEN + OSFD_STRLEN + 3 + 1;
   591     }
   592     if (newSize > attr->fdInheritBufferSize) {
   593         /* Make newSize a multiple of FD_INHERIT_BUFFER_INCR */
   594         remainder = newSize % FD_INHERIT_BUFFER_INCR;
   595         if (remainder != 0) {
   596             newSize += (FD_INHERIT_BUFFER_INCR - remainder);
   597         }
   598         if (NULL == attr->fdInheritBuffer) {
   599             newBuffer = (char *) PR_MALLOC(newSize);
   600         } else {
   601             newBuffer = (char *) PR_REALLOC(attr->fdInheritBuffer, newSize);
   602         }
   603         if (NULL == newBuffer) {
   604             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   605             return PR_FAILURE;
   606         }
   607         attr->fdInheritBuffer = newBuffer;
   608         attr->fdInheritBufferSize = newSize;
   609     }
   610     cur = attr->fdInheritBuffer + attr->fdInheritBufferUsed;
   611     freeSize = attr->fdInheritBufferSize - attr->fdInheritBufferUsed;
   612     if (0 == attr->fdInheritBufferUsed) {
   613         nwritten = PR_snprintf(cur, freeSize,
   614                 "NSPR_INHERIT_FDS=%s:%d:0x%" PR_PRIxOSFD,
   615                 name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
   616     } else {
   617         nwritten = PR_snprintf(cur, freeSize, ":%s:%d:0x%" PR_PRIxOSFD,
   618                 name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
   619     }
   620     attr->fdInheritBufferUsed += nwritten; 
   621     return PR_SUCCESS;
   622 }
   624 PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD(
   625     const char *name)
   626 {
   627     PRFileDesc *fd;
   628     const char *envVar;
   629     const char *ptr;
   630     int len = strlen(name);
   631     PROsfd osfd;
   632     int nColons;
   633     PRIntn fileType;
   635     envVar = PR_GetEnv("NSPR_INHERIT_FDS");
   636     if (NULL == envVar || '\0' == envVar[0]) {
   637         PR_SetError(PR_UNKNOWN_ERROR, 0);
   638         return NULL;
   639     }
   641     ptr = envVar;
   642     while (1) {
   643         if ((ptr[len] == ':') && (strncmp(ptr, name, len) == 0)) {
   644             ptr += len + 1;
   645             PR_sscanf(ptr, "%d:0x%" PR_SCNxOSFD, &fileType, &osfd);
   646             switch ((PRDescType)fileType) {
   647                 case PR_DESC_FILE:
   648                     fd = PR_ImportFile(osfd);
   649                     break;
   650                 case PR_DESC_PIPE:
   651                     fd = PR_ImportPipe(osfd);
   652                     break;
   653                 case PR_DESC_SOCKET_TCP:
   654                     fd = PR_ImportTCPSocket(osfd);
   655                     break;
   656                 case PR_DESC_SOCKET_UDP:
   657                     fd = PR_ImportUDPSocket(osfd);
   658                     break;
   659                 default:
   660                     PR_ASSERT(0);
   661                     PR_SetError(PR_UNKNOWN_ERROR, 0);
   662                     fd = NULL;
   663                     break;
   664             }
   665             if (fd) {
   666                 /*
   667                  * An inherited FD is inheritable by default.
   668                  * The child process needs to call PR_SetFDInheritable
   669                  * to make it non-inheritable if so desired.
   670                  */
   671                 fd->secret->inheritable = _PR_TRI_TRUE;
   672             }
   673             return fd;
   674         }
   675         /* Skip three colons */
   676         nColons = 0;
   677         while (*ptr) {
   678             if (*ptr == ':') {
   679                 if (++nColons == 3) {
   680                     break;
   681                 }
   682             }
   683             ptr++;
   684         }
   685         if (*ptr == '\0') {
   686             PR_SetError(PR_UNKNOWN_ERROR, 0);
   687             return NULL;
   688         }
   689         ptr++;
   690     }
   691 }
   693 PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
   694     const char *path,
   695     char *const *argv,
   696     char *const *envp,
   697     const PRProcessAttr *attr)
   698 {
   699     return _PR_MD_CREATE_PROCESS(path, argv, envp, attr);
   700 }  /* PR_CreateProcess */
   702 PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached(
   703     const char *path,
   704     char *const *argv,
   705     char *const *envp,
   706     const PRProcessAttr *attr)
   707 {
   708     PRProcess *process;
   709     PRStatus rv;
   711     process = PR_CreateProcess(path, argv, envp, attr);
   712     if (NULL == process) {
   713 	return PR_FAILURE;
   714     }
   715     rv = PR_DetachProcess(process);
   716     PR_ASSERT(PR_SUCCESS == rv);
   717     if (rv == PR_FAILURE) {
   718 	PR_DELETE(process);
   719 	return PR_FAILURE;
   720     }
   721     return PR_SUCCESS;
   722 }
   724 PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process)
   725 {
   726     return _PR_MD_DETACH_PROCESS(process);
   727 }
   729 PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode)
   730 {
   731     return _PR_MD_WAIT_PROCESS(process, exitCode);
   732 }  /* PR_WaitProcess */
   734 PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process)
   735 {
   736     return _PR_MD_KILL_PROCESS(process);
   737 }
   739 /*
   740  ********************************************************************
   741  *
   742  * Module initialization
   743  *
   744  ********************************************************************
   745  */
   747 static struct {
   748     PRLock *ml;
   749     PRCondVar *cv;
   750 } mod_init;
   752 static void _PR_InitCallOnce(void) {
   753     mod_init.ml = PR_NewLock();
   754     PR_ASSERT(NULL != mod_init.ml);
   755     mod_init.cv = PR_NewCondVar(mod_init.ml);
   756     PR_ASSERT(NULL != mod_init.cv);
   757 }
   759 void _PR_CleanupCallOnce()
   760 {
   761     PR_DestroyLock(mod_init.ml);
   762     mod_init.ml = NULL;
   763     PR_DestroyCondVar(mod_init.cv);
   764     mod_init.cv = NULL;
   765 }
   767 PR_IMPLEMENT(PRStatus) PR_CallOnce(
   768     PRCallOnceType *once,
   769     PRCallOnceFN    func)
   770 {
   771     if (!_pr_initialized) _PR_ImplicitInitialization();
   773     if (!once->initialized) {
   774 	if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
   775 	    once->status = (*func)();
   776 	    PR_Lock(mod_init.ml);
   777 	    once->initialized = 1;
   778 	    PR_NotifyAllCondVar(mod_init.cv);
   779 	    PR_Unlock(mod_init.ml);
   780 	} else {
   781 	    PR_Lock(mod_init.ml);
   782 	    while (!once->initialized) {
   783 		PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
   784             }
   785 	    PR_Unlock(mod_init.ml);
   786 	}
   787     } else {
   788         if (PR_SUCCESS != once->status) {
   789             PR_SetError(PR_CALL_ONCE_ERROR, 0);
   790         }
   791     }
   792     return once->status;
   793 }
   795 PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
   796     PRCallOnceType      *once,
   797     PRCallOnceWithArgFN  func,
   798     void                *arg)
   799 {
   800     if (!_pr_initialized) _PR_ImplicitInitialization();
   802     if (!once->initialized) {
   803 	if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
   804 	    once->status = (*func)(arg);
   805 	    PR_Lock(mod_init.ml);
   806 	    once->initialized = 1;
   807 	    PR_NotifyAllCondVar(mod_init.cv);
   808 	    PR_Unlock(mod_init.ml);
   809 	} else {
   810 	    PR_Lock(mod_init.ml);
   811 	    while (!once->initialized) {
   812 		PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
   813             }
   814 	    PR_Unlock(mod_init.ml);
   815 	}
   816     } else {
   817         if (PR_SUCCESS != once->status) {
   818             PR_SetError(PR_CALL_ONCE_ERROR, 0);
   819         }
   820     }
   821     return once->status;
   822 }
   824 PRBool _PR_Obsolete(const char *obsolete, const char *preferred)
   825 {
   826 #if defined(DEBUG)
   827     PR_fprintf(
   828         PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n",
   829         obsolete, (NULL == preferred) ? "something else" : preferred);
   830 #endif
   831     return PR_FALSE;
   832 }  /* _PR_Obsolete */
   834 /* prinit.c */

mercurial