VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinit.c@ 101793

Last change on this file since 101793 was 101793, checked in by vboxsync, 13 months ago

libs/xpcom: Start dropping network related abilites as we don't require it at all, we only need local unix sockets (incomplete), bugref:10545

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette