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 *) &top;
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
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)