LCOV - code coverage report
Current view: directory - nsprpub/pr/src/misc - prinit.c (source / functions) Found Hit Coverage
Test: app.info Lines: 261 107 41.0 %
Date: 2012-06-02 Functions: 29 14 48.3 %

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

Generated by: LCOV version 1.7