1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/misc/prinit.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,836 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "primpl.h" 1.10 +#include <ctype.h> 1.11 +#include <string.h> 1.12 + 1.13 +PRLogModuleInfo *_pr_clock_lm; 1.14 +PRLogModuleInfo *_pr_cmon_lm; 1.15 +PRLogModuleInfo *_pr_io_lm; 1.16 +PRLogModuleInfo *_pr_cvar_lm; 1.17 +PRLogModuleInfo *_pr_mon_lm; 1.18 +PRLogModuleInfo *_pr_linker_lm; 1.19 +PRLogModuleInfo *_pr_sched_lm; 1.20 +PRLogModuleInfo *_pr_thread_lm; 1.21 +PRLogModuleInfo *_pr_gc_lm; 1.22 +PRLogModuleInfo *_pr_shm_lm; 1.23 +PRLogModuleInfo *_pr_shma_lm; 1.24 + 1.25 +PRFileDesc *_pr_stdin; 1.26 +PRFileDesc *_pr_stdout; 1.27 +PRFileDesc *_pr_stderr; 1.28 + 1.29 +#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) 1.30 + 1.31 +PRCList _pr_active_local_threadQ = 1.32 + PR_INIT_STATIC_CLIST(&_pr_active_local_threadQ); 1.33 +PRCList _pr_active_global_threadQ = 1.34 + PR_INIT_STATIC_CLIST(&_pr_active_global_threadQ); 1.35 + 1.36 +_MDLock _pr_cpuLock; /* lock for the CPU Q */ 1.37 +PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ); 1.38 + 1.39 +PRUint32 _pr_utid; 1.40 + 1.41 +PRInt32 _pr_userActive; 1.42 +PRInt32 _pr_systemActive; 1.43 +PRUintn _pr_maxPTDs; 1.44 + 1.45 +#ifdef _PR_LOCAL_THREADS_ONLY 1.46 + 1.47 +struct _PRCPU *_pr_currentCPU; 1.48 +PRThread *_pr_currentThread; 1.49 +PRThread *_pr_lastThread; 1.50 +PRInt32 _pr_intsOff; 1.51 + 1.52 +#endif /* _PR_LOCAL_THREADS_ONLY */ 1.53 + 1.54 +/* Lock protecting all "termination" condition variables of all threads */ 1.55 +PRLock *_pr_terminationCVLock; 1.56 + 1.57 +#endif /* !defined(_PR_PTHREADS) */ 1.58 + 1.59 +PRLock *_pr_sleeplock; /* used in PR_Sleep(), classic and pthreads */ 1.60 + 1.61 +static void _PR_InitCallOnce(void); 1.62 + 1.63 +PRBool _pr_initialized = PR_FALSE; 1.64 + 1.65 + 1.66 +PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion) 1.67 +{ 1.68 + /* 1.69 + ** This is the secret handshake algorithm. 1.70 + ** 1.71 + ** This release has a simple version compatibility 1.72 + ** check algorithm. This release is not backward 1.73 + ** compatible with previous major releases. It is 1.74 + ** not compatible with future major, minor, or 1.75 + ** patch releases. 1.76 + */ 1.77 + int vmajor = 0, vminor = 0, vpatch = 0; 1.78 + const char *ptr = importedVersion; 1.79 + 1.80 + while (isdigit(*ptr)) { 1.81 + vmajor = 10 * vmajor + *ptr - '0'; 1.82 + ptr++; 1.83 + } 1.84 + if (*ptr == '.') { 1.85 + ptr++; 1.86 + while (isdigit(*ptr)) { 1.87 + vminor = 10 * vminor + *ptr - '0'; 1.88 + ptr++; 1.89 + } 1.90 + if (*ptr == '.') { 1.91 + ptr++; 1.92 + while (isdigit(*ptr)) { 1.93 + vpatch = 10 * vpatch + *ptr - '0'; 1.94 + ptr++; 1.95 + } 1.96 + } 1.97 + } 1.98 + 1.99 + if (vmajor != PR_VMAJOR) { 1.100 + return PR_FALSE; 1.101 + } 1.102 + if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) { 1.103 + return PR_FALSE; 1.104 + } 1.105 + if (vmajor == PR_VMAJOR && vminor == PR_VMINOR && vpatch > PR_VPATCH) { 1.106 + return PR_FALSE; 1.107 + } 1.108 + return PR_TRUE; 1.109 +} /* PR_VersionCheck */ 1.110 + 1.111 +PR_IMPLEMENT(const char*) PR_GetVersion(void) 1.112 +{ 1.113 + return PR_VERSION; 1.114 +} 1.115 + 1.116 +PR_IMPLEMENT(PRBool) PR_Initialized(void) 1.117 +{ 1.118 + return _pr_initialized; 1.119 +} 1.120 + 1.121 +PRInt32 _native_threads_only = 0; 1.122 + 1.123 +#ifdef WINNT 1.124 +static void _pr_SetNativeThreadsOnlyMode(void) 1.125 +{ 1.126 + HMODULE mainExe; 1.127 + PRBool *globalp; 1.128 + char *envp; 1.129 + 1.130 + mainExe = GetModuleHandle(NULL); 1.131 + PR_ASSERT(NULL != mainExe); 1.132 + globalp = (PRBool *) GetProcAddress(mainExe, "nspr_native_threads_only"); 1.133 + if (globalp) { 1.134 + _native_threads_only = (*globalp != PR_FALSE); 1.135 + } else if (envp = getenv("NSPR_NATIVE_THREADS_ONLY")) { 1.136 + _native_threads_only = (atoi(envp) == 1); 1.137 + } 1.138 +} 1.139 +#endif 1.140 + 1.141 +static void _PR_InitStuff(void) 1.142 +{ 1.143 + 1.144 + if (_pr_initialized) return; 1.145 + _pr_initialized = PR_TRUE; 1.146 +#ifdef _PR_ZONE_ALLOCATOR 1.147 + _PR_InitZones(); 1.148 +#endif 1.149 +#ifdef WINNT 1.150 + _pr_SetNativeThreadsOnlyMode(); 1.151 +#endif 1.152 + 1.153 + 1.154 + (void) PR_GetPageSize(); 1.155 + 1.156 + _pr_clock_lm = PR_NewLogModule("clock"); 1.157 + _pr_cmon_lm = PR_NewLogModule("cmon"); 1.158 + _pr_io_lm = PR_NewLogModule("io"); 1.159 + _pr_mon_lm = PR_NewLogModule("mon"); 1.160 + _pr_linker_lm = PR_NewLogModule("linker"); 1.161 + _pr_cvar_lm = PR_NewLogModule("cvar"); 1.162 + _pr_sched_lm = PR_NewLogModule("sched"); 1.163 + _pr_thread_lm = PR_NewLogModule("thread"); 1.164 + _pr_gc_lm = PR_NewLogModule("gc"); 1.165 + _pr_shm_lm = PR_NewLogModule("shm"); 1.166 + _pr_shma_lm = PR_NewLogModule("shma"); 1.167 + 1.168 + /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */ 1.169 + _PR_MD_EARLY_INIT(); 1.170 + 1.171 + _PR_InitLocks(); 1.172 + _PR_InitAtomic(); 1.173 + _PR_InitSegs(); 1.174 + _PR_InitStacks(); 1.175 + _PR_InitTPD(); 1.176 + _PR_InitEnv(); 1.177 + _PR_InitLayerCache(); 1.178 + _PR_InitClock(); 1.179 + 1.180 + _pr_sleeplock = PR_NewLock(); 1.181 + PR_ASSERT(NULL != _pr_sleeplock); 1.182 + 1.183 + _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 1.184 + 1.185 +#ifdef WIN16 1.186 + { 1.187 + PRInt32 top; /* artificial top of stack, win16 */ 1.188 + _pr_top_of_task_stack = (char *) ⊤ 1.189 + } 1.190 +#endif 1.191 + 1.192 +#ifndef _PR_GLOBAL_THREADS_ONLY 1.193 + _PR_InitCPUs(); 1.194 +#endif 1.195 + 1.196 +/* 1.197 + * XXX: call _PR_InitMem only on those platforms for which nspr implements 1.198 + * malloc, for now. 1.199 + */ 1.200 +#ifdef _PR_OVERRIDE_MALLOC 1.201 + _PR_InitMem(); 1.202 +#endif 1.203 + 1.204 + _PR_InitCMon(); 1.205 + _PR_InitIO(); 1.206 + _PR_InitNet(); 1.207 + _PR_InitTime(); 1.208 + _PR_InitLog(); 1.209 + _PR_InitLinker(); 1.210 + _PR_InitCallOnce(); 1.211 + _PR_InitDtoa(); 1.212 + _PR_InitMW(); 1.213 + _PR_InitRWLocks(); 1.214 + 1.215 + nspr_InitializePRErrorTable(); 1.216 + 1.217 + _PR_MD_FINAL_INIT(); 1.218 +} 1.219 + 1.220 +void _PR_ImplicitInitialization(void) 1.221 +{ 1.222 + _PR_InitStuff(); 1.223 + 1.224 + /* Enable interrupts */ 1.225 +#if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) 1.226 + _PR_MD_START_INTERRUPTS(); 1.227 +#endif 1.228 + 1.229 +} 1.230 + 1.231 +PR_IMPLEMENT(void) PR_DisableClockInterrupts(void) 1.232 +{ 1.233 +#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) 1.234 + if (!_pr_initialized) { 1.235 + _PR_InitStuff(); 1.236 + } else { 1.237 + _PR_MD_DISABLE_CLOCK_INTERRUPTS(); 1.238 + } 1.239 +#endif 1.240 +} 1.241 + 1.242 +PR_IMPLEMENT(void) PR_EnableClockInterrupts(void) 1.243 +{ 1.244 +#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) 1.245 + if (!_pr_initialized) { 1.246 + _PR_InitStuff(); 1.247 + } 1.248 + _PR_MD_ENABLE_CLOCK_INTERRUPTS(); 1.249 +#endif 1.250 +} 1.251 + 1.252 +PR_IMPLEMENT(void) PR_BlockClockInterrupts(void) 1.253 +{ 1.254 +#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) 1.255 + _PR_MD_BLOCK_CLOCK_INTERRUPTS(); 1.256 +#endif 1.257 +} 1.258 + 1.259 +PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void) 1.260 +{ 1.261 +#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) 1.262 + _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(); 1.263 +#endif 1.264 +} 1.265 + 1.266 +PR_IMPLEMENT(void) PR_Init( 1.267 + PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs) 1.268 +{ 1.269 + _PR_ImplicitInitialization(); 1.270 +} 1.271 + 1.272 +PR_IMPLEMENT(PRIntn) PR_Initialize( 1.273 + PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs) 1.274 +{ 1.275 + PRIntn rv; 1.276 + _PR_ImplicitInitialization(); 1.277 + rv = prmain(argc, argv); 1.278 + PR_Cleanup(); 1.279 + return rv; 1.280 +} /* PR_Initialize */ 1.281 + 1.282 +/* 1.283 + *----------------------------------------------------------------------- 1.284 + * 1.285 + * _PR_CleanupBeforeExit -- 1.286 + * 1.287 + * Perform the cleanup work before exiting the process. 1.288 + * We first do the cleanup generic to all platforms. Then 1.289 + * we call _PR_MD_CLEANUP_BEFORE_EXIT(), where platform-dependent 1.290 + * cleanup is done. This function is used by PR_Cleanup(). 1.291 + * 1.292 + * See also: PR_Cleanup(). 1.293 + * 1.294 + *----------------------------------------------------------------------- 1.295 + */ 1.296 +#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS) 1.297 + /* see ptthread.c */ 1.298 +#else 1.299 +static void 1.300 +_PR_CleanupBeforeExit(void) 1.301 +{ 1.302 +/* 1.303 +Do not make any calls here other than to destroy resources. For example, 1.304 +do not make any calls that eventually may end up in PR_Lock. Because the 1.305 +thread is destroyed, can not access current thread any more. 1.306 +*/ 1.307 + _PR_CleanupTPD(); 1.308 + if (_pr_terminationCVLock) 1.309 + /* 1.310 + * In light of the comment above, this looks real suspicious. 1.311 + * I'd go so far as to say it's just a problem waiting to happen. 1.312 + */ 1.313 + PR_DestroyLock(_pr_terminationCVLock); 1.314 + 1.315 + _PR_MD_CLEANUP_BEFORE_EXIT(); 1.316 +} 1.317 +#endif /* defined(_PR_PTHREADS) */ 1.318 + 1.319 +/* 1.320 + *---------------------------------------------------------------------- 1.321 + * 1.322 + * PR_Cleanup -- 1.323 + * 1.324 + * Perform a graceful shutdown of the NSPR runtime. PR_Cleanup() may 1.325 + * only be called from the primordial thread, typically at the 1.326 + * end of the main() function. It returns when it has completed 1.327 + * its platform-dependent duty and the process must not make any other 1.328 + * NSPR library calls prior to exiting from main(). 1.329 + * 1.330 + * PR_Cleanup() first blocks the primordial thread until all the 1.331 + * other user (non-system) threads, if any, have terminated. 1.332 + * Then it performs cleanup in preparation for exiting the process. 1.333 + * PR_Cleanup() does not exit the primordial thread (which would 1.334 + * in turn exit the process). 1.335 + * 1.336 + * PR_Cleanup() only responds when it is called by the primordial 1.337 + * thread. Calls by any other thread are silently ignored. 1.338 + * 1.339 + * See also: PR_ExitProcess() 1.340 + * 1.341 + *---------------------------------------------------------------------- 1.342 + */ 1.343 +#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS) 1.344 + /* see ptthread.c */ 1.345 +#else 1.346 + 1.347 +PR_IMPLEMENT(PRStatus) PR_Cleanup() 1.348 +{ 1.349 + PRThread *me = PR_GetCurrentThread(); 1.350 + PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL)); 1.351 + if ((NULL != me) && (me->flags & _PR_PRIMORDIAL)) 1.352 + { 1.353 + PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); 1.354 + 1.355 + /* 1.356 + * No more recycling of threads 1.357 + */ 1.358 + _pr_recycleThreads = 0; 1.359 + 1.360 + /* 1.361 + * Wait for all other user (non-system/daemon) threads 1.362 + * to terminate. 1.363 + */ 1.364 + PR_Lock(_pr_activeLock); 1.365 + while (_pr_userActive > _pr_primordialExitCount) { 1.366 + PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT); 1.367 + } 1.368 + if (me->flags & _PR_SYSTEM) { 1.369 + _pr_systemActive--; 1.370 + } else { 1.371 + _pr_userActive--; 1.372 + } 1.373 + PR_Unlock(_pr_activeLock); 1.374 + 1.375 +#ifdef IRIX 1.376 + _PR_MD_PRE_CLEANUP(me); 1.377 + /* 1.378 + * The primordial thread must now be running on the primordial cpu 1.379 + */ 1.380 + PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0)); 1.381 +#endif 1.382 + 1.383 + _PR_MD_EARLY_CLEANUP(); 1.384 + 1.385 + _PR_CleanupMW(); 1.386 + _PR_CleanupTime(); 1.387 + _PR_CleanupDtoa(); 1.388 + _PR_CleanupCallOnce(); 1.389 + _PR_ShutdownLinker(); 1.390 + _PR_CleanupNet(); 1.391 + _PR_CleanupIO(); 1.392 + /* Release the primordial thread's private data, etc. */ 1.393 + _PR_CleanupThread(me); 1.394 + 1.395 + _PR_MD_STOP_INTERRUPTS(); 1.396 + 1.397 + PR_LOG(_pr_thread_lm, PR_LOG_MIN, 1.398 + ("PR_Cleanup: clean up before destroying thread")); 1.399 + _PR_LogCleanup(); 1.400 + 1.401 + /* 1.402 + * This part should look like the end of _PR_NativeRunThread 1.403 + * and _PR_UserRunThread. 1.404 + */ 1.405 + if (_PR_IS_NATIVE_THREAD(me)) { 1.406 + _PR_MD_EXIT_THREAD(me); 1.407 + _PR_NativeDestroyThread(me); 1.408 + } else { 1.409 + _PR_UserDestroyThread(me); 1.410 + PR_DELETE(me->stack); 1.411 + PR_DELETE(me); 1.412 + } 1.413 + 1.414 + /* 1.415 + * XXX: We are freeing the heap memory here so that Purify won't 1.416 + * complain, but we should also free other kinds of resources 1.417 + * that are allocated by the _PR_InitXXX() functions. 1.418 + * Ideally, for each _PR_InitXXX(), there should be a corresponding 1.419 + * _PR_XXXCleanup() that we can call here. 1.420 + */ 1.421 +#ifdef WINNT 1.422 + _PR_CleanupCPUs(); 1.423 +#endif 1.424 + _PR_CleanupThreads(); 1.425 + _PR_CleanupCMon(); 1.426 + PR_DestroyLock(_pr_sleeplock); 1.427 + _pr_sleeplock = NULL; 1.428 + _PR_CleanupLayerCache(); 1.429 + _PR_CleanupEnv(); 1.430 + _PR_CleanupStacks(); 1.431 + _PR_CleanupBeforeExit(); 1.432 + _pr_initialized = PR_FALSE; 1.433 + return PR_SUCCESS; 1.434 + } 1.435 + return PR_FAILURE; 1.436 +} 1.437 +#endif /* defined(_PR_PTHREADS) */ 1.438 + 1.439 +/* 1.440 + *------------------------------------------------------------------------ 1.441 + * PR_ProcessExit -- 1.442 + * 1.443 + * Cause an immediate, nongraceful, forced termination of the process. 1.444 + * It takes a PRIntn argument, which is the exit status code of the 1.445 + * process. 1.446 + * 1.447 + * See also: PR_Cleanup() 1.448 + * 1.449 + *------------------------------------------------------------------------ 1.450 + */ 1.451 + 1.452 +#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS) 1.453 + /* see ptthread.c */ 1.454 +#else 1.455 +PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status) 1.456 +{ 1.457 + _PR_MD_EXIT(status); 1.458 +} 1.459 + 1.460 +#endif /* defined(_PR_PTHREADS) */ 1.461 + 1.462 +PR_IMPLEMENT(PRProcessAttr *) 1.463 +PR_NewProcessAttr(void) 1.464 +{ 1.465 + PRProcessAttr *attr; 1.466 + 1.467 + attr = PR_NEWZAP(PRProcessAttr); 1.468 + if (!attr) { 1.469 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.470 + } 1.471 + return attr; 1.472 +} 1.473 + 1.474 +PR_IMPLEMENT(void) 1.475 +PR_ResetProcessAttr(PRProcessAttr *attr) 1.476 +{ 1.477 + PR_FREEIF(attr->currentDirectory); 1.478 + PR_FREEIF(attr->fdInheritBuffer); 1.479 + memset(attr, 0, sizeof(*attr)); 1.480 +} 1.481 + 1.482 +PR_IMPLEMENT(void) 1.483 +PR_DestroyProcessAttr(PRProcessAttr *attr) 1.484 +{ 1.485 + PR_FREEIF(attr->currentDirectory); 1.486 + PR_FREEIF(attr->fdInheritBuffer); 1.487 + PR_DELETE(attr); 1.488 +} 1.489 + 1.490 +PR_IMPLEMENT(void) 1.491 +PR_ProcessAttrSetStdioRedirect( 1.492 + PRProcessAttr *attr, 1.493 + PRSpecialFD stdioFd, 1.494 + PRFileDesc *redirectFd) 1.495 +{ 1.496 + switch (stdioFd) { 1.497 + case PR_StandardInput: 1.498 + attr->stdinFd = redirectFd; 1.499 + break; 1.500 + case PR_StandardOutput: 1.501 + attr->stdoutFd = redirectFd; 1.502 + break; 1.503 + case PR_StandardError: 1.504 + attr->stderrFd = redirectFd; 1.505 + break; 1.506 + default: 1.507 + PR_ASSERT(0); 1.508 + } 1.509 +} 1.510 + 1.511 +/* 1.512 + * OBSOLETE 1.513 + */ 1.514 +PR_IMPLEMENT(void) 1.515 +PR_SetStdioRedirect( 1.516 + PRProcessAttr *attr, 1.517 + PRSpecialFD stdioFd, 1.518 + PRFileDesc *redirectFd) 1.519 +{ 1.520 +#if defined(DEBUG) 1.521 + static PRBool warn = PR_TRUE; 1.522 + if (warn) { 1.523 + warn = _PR_Obsolete("PR_SetStdioRedirect()", 1.524 + "PR_ProcessAttrSetStdioRedirect()"); 1.525 + } 1.526 +#endif 1.527 + PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd); 1.528 +} 1.529 + 1.530 +PR_IMPLEMENT(PRStatus) 1.531 +PR_ProcessAttrSetCurrentDirectory( 1.532 + PRProcessAttr *attr, 1.533 + const char *dir) 1.534 +{ 1.535 + PR_FREEIF(attr->currentDirectory); 1.536 + attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1); 1.537 + if (!attr->currentDirectory) { 1.538 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.539 + return PR_FAILURE; 1.540 + } 1.541 + strcpy(attr->currentDirectory, dir); 1.542 + return PR_SUCCESS; 1.543 +} 1.544 + 1.545 +PR_IMPLEMENT(PRStatus) 1.546 +PR_ProcessAttrSetInheritableFD( 1.547 + PRProcessAttr *attr, 1.548 + PRFileDesc *fd, 1.549 + const char *name) 1.550 +{ 1.551 + /* We malloc the fd inherit buffer in multiples of this number. */ 1.552 +#define FD_INHERIT_BUFFER_INCR 128 1.553 + /* The length of "NSPR_INHERIT_FDS=" */ 1.554 +#define NSPR_INHERIT_FDS_STRLEN 17 1.555 + /* The length of osfd (PROsfd) printed in hexadecimal with 0x prefix */ 1.556 +#ifdef _WIN64 1.557 +#define OSFD_STRLEN 18 1.558 +#else 1.559 +#define OSFD_STRLEN 10 1.560 +#endif 1.561 + /* The length of fd type (PRDescType) printed in decimal */ 1.562 +#define FD_TYPE_STRLEN 1 1.563 + PRSize newSize; 1.564 + int remainder; 1.565 + char *newBuffer; 1.566 + int nwritten; 1.567 + char *cur; 1.568 + int freeSize; 1.569 + 1.570 + if (fd->identity != PR_NSPR_IO_LAYER) { 1.571 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.572 + return PR_FAILURE; 1.573 + } 1.574 + if (fd->secret->inheritable == _PR_TRI_UNKNOWN) { 1.575 + _PR_MD_QUERY_FD_INHERITABLE(fd); 1.576 + } 1.577 + if (fd->secret->inheritable != _PR_TRI_TRUE) { 1.578 + PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0); 1.579 + return PR_FAILURE; 1.580 + } 1.581 + 1.582 + /* 1.583 + * We also need to account for the : separators and the 1.584 + * terminating null byte. 1.585 + */ 1.586 + if (NULL == attr->fdInheritBuffer) { 1.587 + /* The first time, we print "NSPR_INHERIT_FDS=<name>:<type>:<val>" */ 1.588 + newSize = NSPR_INHERIT_FDS_STRLEN + strlen(name) 1.589 + + FD_TYPE_STRLEN + OSFD_STRLEN + 2 + 1; 1.590 + } else { 1.591 + /* At other times, we print ":<name>:<type>:<val>" */ 1.592 + newSize = attr->fdInheritBufferUsed + strlen(name) 1.593 + + FD_TYPE_STRLEN + OSFD_STRLEN + 3 + 1; 1.594 + } 1.595 + if (newSize > attr->fdInheritBufferSize) { 1.596 + /* Make newSize a multiple of FD_INHERIT_BUFFER_INCR */ 1.597 + remainder = newSize % FD_INHERIT_BUFFER_INCR; 1.598 + if (remainder != 0) { 1.599 + newSize += (FD_INHERIT_BUFFER_INCR - remainder); 1.600 + } 1.601 + if (NULL == attr->fdInheritBuffer) { 1.602 + newBuffer = (char *) PR_MALLOC(newSize); 1.603 + } else { 1.604 + newBuffer = (char *) PR_REALLOC(attr->fdInheritBuffer, newSize); 1.605 + } 1.606 + if (NULL == newBuffer) { 1.607 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.608 + return PR_FAILURE; 1.609 + } 1.610 + attr->fdInheritBuffer = newBuffer; 1.611 + attr->fdInheritBufferSize = newSize; 1.612 + } 1.613 + cur = attr->fdInheritBuffer + attr->fdInheritBufferUsed; 1.614 + freeSize = attr->fdInheritBufferSize - attr->fdInheritBufferUsed; 1.615 + if (0 == attr->fdInheritBufferUsed) { 1.616 + nwritten = PR_snprintf(cur, freeSize, 1.617 + "NSPR_INHERIT_FDS=%s:%d:0x%" PR_PRIxOSFD, 1.618 + name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd); 1.619 + } else { 1.620 + nwritten = PR_snprintf(cur, freeSize, ":%s:%d:0x%" PR_PRIxOSFD, 1.621 + name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd); 1.622 + } 1.623 + attr->fdInheritBufferUsed += nwritten; 1.624 + return PR_SUCCESS; 1.625 +} 1.626 + 1.627 +PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD( 1.628 + const char *name) 1.629 +{ 1.630 + PRFileDesc *fd; 1.631 + const char *envVar; 1.632 + const char *ptr; 1.633 + int len = strlen(name); 1.634 + PROsfd osfd; 1.635 + int nColons; 1.636 + PRIntn fileType; 1.637 + 1.638 + envVar = PR_GetEnv("NSPR_INHERIT_FDS"); 1.639 + if (NULL == envVar || '\0' == envVar[0]) { 1.640 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.641 + return NULL; 1.642 + } 1.643 + 1.644 + ptr = envVar; 1.645 + while (1) { 1.646 + if ((ptr[len] == ':') && (strncmp(ptr, name, len) == 0)) { 1.647 + ptr += len + 1; 1.648 + PR_sscanf(ptr, "%d:0x%" PR_SCNxOSFD, &fileType, &osfd); 1.649 + switch ((PRDescType)fileType) { 1.650 + case PR_DESC_FILE: 1.651 + fd = PR_ImportFile(osfd); 1.652 + break; 1.653 + case PR_DESC_PIPE: 1.654 + fd = PR_ImportPipe(osfd); 1.655 + break; 1.656 + case PR_DESC_SOCKET_TCP: 1.657 + fd = PR_ImportTCPSocket(osfd); 1.658 + break; 1.659 + case PR_DESC_SOCKET_UDP: 1.660 + fd = PR_ImportUDPSocket(osfd); 1.661 + break; 1.662 + default: 1.663 + PR_ASSERT(0); 1.664 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.665 + fd = NULL; 1.666 + break; 1.667 + } 1.668 + if (fd) { 1.669 + /* 1.670 + * An inherited FD is inheritable by default. 1.671 + * The child process needs to call PR_SetFDInheritable 1.672 + * to make it non-inheritable if so desired. 1.673 + */ 1.674 + fd->secret->inheritable = _PR_TRI_TRUE; 1.675 + } 1.676 + return fd; 1.677 + } 1.678 + /* Skip three colons */ 1.679 + nColons = 0; 1.680 + while (*ptr) { 1.681 + if (*ptr == ':') { 1.682 + if (++nColons == 3) { 1.683 + break; 1.684 + } 1.685 + } 1.686 + ptr++; 1.687 + } 1.688 + if (*ptr == '\0') { 1.689 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.690 + return NULL; 1.691 + } 1.692 + ptr++; 1.693 + } 1.694 +} 1.695 + 1.696 +PR_IMPLEMENT(PRProcess*) PR_CreateProcess( 1.697 + const char *path, 1.698 + char *const *argv, 1.699 + char *const *envp, 1.700 + const PRProcessAttr *attr) 1.701 +{ 1.702 + return _PR_MD_CREATE_PROCESS(path, argv, envp, attr); 1.703 +} /* PR_CreateProcess */ 1.704 + 1.705 +PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached( 1.706 + const char *path, 1.707 + char *const *argv, 1.708 + char *const *envp, 1.709 + const PRProcessAttr *attr) 1.710 +{ 1.711 + PRProcess *process; 1.712 + PRStatus rv; 1.713 + 1.714 + process = PR_CreateProcess(path, argv, envp, attr); 1.715 + if (NULL == process) { 1.716 + return PR_FAILURE; 1.717 + } 1.718 + rv = PR_DetachProcess(process); 1.719 + PR_ASSERT(PR_SUCCESS == rv); 1.720 + if (rv == PR_FAILURE) { 1.721 + PR_DELETE(process); 1.722 + return PR_FAILURE; 1.723 + } 1.724 + return PR_SUCCESS; 1.725 +} 1.726 + 1.727 +PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process) 1.728 +{ 1.729 + return _PR_MD_DETACH_PROCESS(process); 1.730 +} 1.731 + 1.732 +PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode) 1.733 +{ 1.734 + return _PR_MD_WAIT_PROCESS(process, exitCode); 1.735 +} /* PR_WaitProcess */ 1.736 + 1.737 +PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process) 1.738 +{ 1.739 + return _PR_MD_KILL_PROCESS(process); 1.740 +} 1.741 + 1.742 +/* 1.743 + ******************************************************************** 1.744 + * 1.745 + * Module initialization 1.746 + * 1.747 + ******************************************************************** 1.748 + */ 1.749 + 1.750 +static struct { 1.751 + PRLock *ml; 1.752 + PRCondVar *cv; 1.753 +} mod_init; 1.754 + 1.755 +static void _PR_InitCallOnce(void) { 1.756 + mod_init.ml = PR_NewLock(); 1.757 + PR_ASSERT(NULL != mod_init.ml); 1.758 + mod_init.cv = PR_NewCondVar(mod_init.ml); 1.759 + PR_ASSERT(NULL != mod_init.cv); 1.760 +} 1.761 + 1.762 +void _PR_CleanupCallOnce() 1.763 +{ 1.764 + PR_DestroyLock(mod_init.ml); 1.765 + mod_init.ml = NULL; 1.766 + PR_DestroyCondVar(mod_init.cv); 1.767 + mod_init.cv = NULL; 1.768 +} 1.769 + 1.770 +PR_IMPLEMENT(PRStatus) PR_CallOnce( 1.771 + PRCallOnceType *once, 1.772 + PRCallOnceFN func) 1.773 +{ 1.774 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.775 + 1.776 + if (!once->initialized) { 1.777 + if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) { 1.778 + once->status = (*func)(); 1.779 + PR_Lock(mod_init.ml); 1.780 + once->initialized = 1; 1.781 + PR_NotifyAllCondVar(mod_init.cv); 1.782 + PR_Unlock(mod_init.ml); 1.783 + } else { 1.784 + PR_Lock(mod_init.ml); 1.785 + while (!once->initialized) { 1.786 + PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); 1.787 + } 1.788 + PR_Unlock(mod_init.ml); 1.789 + } 1.790 + } else { 1.791 + if (PR_SUCCESS != once->status) { 1.792 + PR_SetError(PR_CALL_ONCE_ERROR, 0); 1.793 + } 1.794 + } 1.795 + return once->status; 1.796 +} 1.797 + 1.798 +PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( 1.799 + PRCallOnceType *once, 1.800 + PRCallOnceWithArgFN func, 1.801 + void *arg) 1.802 +{ 1.803 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.804 + 1.805 + if (!once->initialized) { 1.806 + if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) { 1.807 + once->status = (*func)(arg); 1.808 + PR_Lock(mod_init.ml); 1.809 + once->initialized = 1; 1.810 + PR_NotifyAllCondVar(mod_init.cv); 1.811 + PR_Unlock(mod_init.ml); 1.812 + } else { 1.813 + PR_Lock(mod_init.ml); 1.814 + while (!once->initialized) { 1.815 + PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); 1.816 + } 1.817 + PR_Unlock(mod_init.ml); 1.818 + } 1.819 + } else { 1.820 + if (PR_SUCCESS != once->status) { 1.821 + PR_SetError(PR_CALL_ONCE_ERROR, 0); 1.822 + } 1.823 + } 1.824 + return once->status; 1.825 +} 1.826 + 1.827 +PRBool _PR_Obsolete(const char *obsolete, const char *preferred) 1.828 +{ 1.829 +#if defined(DEBUG) 1.830 + PR_fprintf( 1.831 + PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n", 1.832 + obsolete, (NULL == preferred) ? "something else" : preferred); 1.833 +#endif 1.834 + return PR_FALSE; 1.835 +} /* _PR_Obsolete */ 1.836 + 1.837 +/* prinit.c */ 1.838 + 1.839 +