LCOV - app.info - nsprpub/pr/src/misc/prinit.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/misc - prinit.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 261 | 61 | 23.4 %
| Date: | 2012-04-07 | Functions: | 29 | 4 | 13.8 %

           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               0 : PR_IMPLEMENT(PRBool) PR_Initialized(void)
         146                 : {
         147               0 :     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           18667 : static void _PR_InitStuff(void)
         171                 : {
         172                 :
         173           18667 :     if (_pr_initialized) return;
         174           18667 :     _pr_initialized = PR_TRUE;
         175                 : #ifdef _PR_ZONE_ALLOCATOR
         176           18667 :     _PR_InitZones();
         177                 : #endif
         178                 : #ifdef WINNT
         179                 :     _pr_SetNativeThreadsOnlyMode();
         180                 : #endif
         181                 :
         182                 :
         183           18667 :     (void) PR_GetPageSize();
         184                 :
         185           18667 :         _pr_clock_lm = PR_NewLogModule("clock");
         186           18667 :         _pr_cmon_lm = PR_NewLogModule("cmon");
         187           18667 :         _pr_io_lm = PR_NewLogModule("io");
         188           18667 :         _pr_mon_lm = PR_NewLogModule("mon");
         189           18667 :         _pr_linker_lm = PR_NewLogModule("linker");
         190           18667 :         _pr_cvar_lm = PR_NewLogModule("cvar");
         191           18667 :         _pr_sched_lm = PR_NewLogModule("sched");
         192           18667 :         _pr_thread_lm = PR_NewLogModule("thread");
         193           18667 :         _pr_gc_lm = PR_NewLogModule("gc");
         194           18667 :         _pr_shm_lm = PR_NewLogModule("shm");
         195           18667 :         _pr_shma_lm = PR_NewLogModule("shma");
         196                 :
         197                 :     /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */
         198           18667 :     _PR_MD_EARLY_INIT();
         199                 :
         200           18667 :     _PR_InitLocks();
         201           18667 :     _PR_InitAtomic();
         202           18667 :     _PR_InitSegs();
         203           18667 :     _PR_InitStacks();
         204           18667 :         _PR_InitTPD();
         205           18667 :     _PR_InitEnv();
         206           18667 :     _PR_InitLayerCache();
         207           18667 :     _PR_InitClock();
         208                 :
         209           18667 :     _pr_sleeplock = PR_NewLock();
         210           18667 :     PR_ASSERT(NULL != _pr_sleeplock);
         211                 :
         212           18667 :     _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           18667 :         _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           18667 :     _PR_InitCMon();
         234           18667 :     _PR_InitIO();
         235           18667 :     _PR_InitNet();
         236           18667 :     _PR_InitTime();
         237           18667 :     _PR_InitLog();
         238           18667 :     _PR_InitLinker();
         239           18667 :     _PR_InitCallOnce();
         240           18667 :     _PR_InitDtoa();
         241           18667 :     _PR_InitMW();
         242           18667 :     _PR_InitRWLocks();
         243                 :
         244           18667 :     nspr_InitializePRErrorTable();
         245                 :
         246           18667 :     _PR_MD_FINAL_INIT();
         247                 : }
         248                 :
         249           18667 : void _PR_ImplicitInitialization(void)
         250                 : {
         251           18667 :         _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           18667 : }
         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               0 : PR_IMPLEMENT(void) PR_Init(
         296                 :     PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
         297                 : {
         298               0 :     _PR_ImplicitInitialization();
         299               0 : }
         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               0 : PR_NewProcessAttr(void)
         493                 : {
         494                 :     PRProcessAttr *attr;
         495                 :
         496               0 :     attr = PR_NEWZAP(PRProcessAttr);
         497               0 :     if (!attr) {
         498               0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         499                 :     }
         500               0 :     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               0 : PR_DestroyProcessAttr(PRProcessAttr *attr)
         513                 : {
         514               0 :     PR_FREEIF(attr->currentDirectory);
         515               0 :     PR_FREEIF(attr->fdInheritBuffer);
         516               0 :     PR_DELETE(attr);
         517               0 : }
         518                 :
         519                 : PR_IMPLEMENT(void)
         520               0 : PR_ProcessAttrSetStdioRedirect(
         521                 :     PRProcessAttr *attr,
         522                 :     PRSpecialFD stdioFd,
         523                 :     PRFileDesc *redirectFd)
         524                 : {
         525               0 :     switch (stdioFd) {
         526                 :         case PR_StandardInput:
         527               0 :             attr->stdinFd = redirectFd;
         528               0 :             break;
         529                 :         case PR_StandardOutput:
         530               0 :             attr->stdoutFd = redirectFd;
         531               0 :             break;
         532                 :         case PR_StandardError:
         533               0 :             attr->stderrFd = redirectFd;
         534               0 :             break;
         535                 :         default:
         536               0 :             PR_ASSERT(0);
         537                 :     }
         538               0 : }
         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               0 : PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
         726                 :     const char *path,
         727                 :     char *const *argv,
         728                 :     char *const *envp,
         729                 :     const PRProcessAttr *attr)
         730                 : {
         731               0 :     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               0 : PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode)
         762                 : {
         763               0 :     return _PR_MD_WAIT_PROCESS(process, exitCode);
         764                 : }  /* PR_WaitProcess */
         765                 :
         766               0 : PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process)
         767                 : {
         768               0 :     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           18667 : static void _PR_InitCallOnce(void) {
         785           18667 :     mod_init.ml = PR_NewLock();
         786           18667 :     PR_ASSERT(NULL != mod_init.ml);
         787           18667 :     mod_init.cv = PR_NewCondVar(mod_init.ml);
         788           18667 :     PR_ASSERT(NULL != mod_init.cv);
         789           18667 : }
         790                 :
         791               0 : void _PR_CleanupCallOnce()
         792                 : {
         793               0 :     PR_DestroyLock(mod_init.ml);
         794               0 :     mod_init.ml = NULL;
         795               0 :     PR_DestroyCondVar(mod_init.cv);
         796               0 :     mod_init.cv = NULL;
         797               0 : }
         798                 :
         799               0 : PR_IMPLEMENT(PRStatus) PR_CallOnce(
         800                 :     PRCallOnceType *once,
         801                 :     PRCallOnceFN    func)
         802                 : {
         803               0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
         804                 :
         805               0 :     if (!once->initialized) {
         806               0 :         if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
         807               0 :             once->status = (*func)();
         808               0 :             PR_Lock(mod_init.ml);
         809               0 :             once->initialized = 1;
         810               0 :             PR_NotifyAllCondVar(mod_init.cv);
         811               0 :             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               0 :         if (PR_SUCCESS != once->status) {
         821               0 :             PR_SetError(PR_CALL_ONCE_ERROR, 0);
         822                 :         }
         823                 :     }
         824               0 :     return once->status;
         825                 : }
         826                 :
         827           18761 : PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
         828                 :     PRCallOnceType      *once,
         829                 :     PRCallOnceWithArgFN  func,
         830                 :     void                *arg)
         831                 : {
         832           18761 :     if (!_pr_initialized) _PR_ImplicitInitialization();
         833                 :
         834           18761 :     if (!once->initialized) {
         835           18667 :         if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
         836           18667 :             once->status = (*func)(arg);
         837           18667 :             PR_Lock(mod_init.ml);
         838           18667 :             once->initialized = 1;
         839           18667 :             PR_NotifyAllCondVar(mod_init.cv);
         840           18667 :             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              94 :         if (PR_SUCCESS != once->status) {
         850               0 :             PR_SetError(PR_CALL_ONCE_ERROR, 0);
         851                 :         }
         852                 :     }
         853           18761 :     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