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