VirtualBox

Changeset 23869 in vbox


Ignore:
Timestamp:
Oct 19, 2009 2:32:57 PM (15 years ago)
Author:
vboxsync
Message:

fix/hack waitpid issues for unix platforms: racing of RT and xpcom, make waitpid for terminated child processes

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/init.cpp

    r21890 r23869  
    4242# ifndef RT_OS_OS2
    4343#  include <pthread.h>
     44#  include <signal.h>
     45#  include <errno.h>
     46#  define IPRT_USE_SIG_CHILD_DUMMY
    4447# endif
    4548#endif
     
    204207}
    205208
     209
     210#ifdef IPRT_USE_SIG_CHILD_DUMMY
     211/**
     212 * Dummy SIGCHILD handler.
     213 *
     214 * Assigned on rtR3Init only when SIGCHILD handler is set SIGIGN or SIGDEF to
     215 * ensure waitpid works properly for the terminated processes.
     216 */
     217static void rtR3SigChildHandler(int iSignal)
     218{
     219    NOREF(iSignal);
     220}
     221#endif /* IPRT_USE_SIG_CHILD_DUMMY */
     222
     223
    206224/**
    207225 * rtR3Init worker.
     
    296314    atexit(rtR3ExitCallback);
    297315
     316#ifdef IPRT_USE_SIG_CHILD_DUMMY
     317    /*
     318     * SIGCHLD must not be ignored (that's default), otherwise posix compliant waitpid
     319     * implementations won't work right.
     320     */
     321    for (;;)
     322    {
     323        struct sigaction saOld;
     324        rc = sigaction(SIGCHLD, 0, &saOld);         AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
     325        if (    rc != 0
     326            ||  (saOld.sa_flags & SA_SIGINFO)
     327            || (   saOld.sa_handler != SIG_IGN
     328                && saOld.sa_handler != SIG_DFL)
     329           )
     330            break;
     331
     332        /* Try install dummy handler. */
     333        struct sigaction saNew = saOld;
     334        saNew.sa_flags   = SA_NOCLDSTOP | SA_RESTART;
     335        saNew.sa_handler = rtR3SigChildHandler;
     336        rc = sigemptyset(&saNew.sa_mask);           AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
     337        struct sigaction saOld2;
     338        rc = sigaction(SIGCHLD, &saNew, &saOld2);   AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
     339        if (    rc != 0
     340            ||  (   saOld2.sa_handler == saOld.sa_handler
     341                 && saOld2.sa_flags == saOld.sa_flags)
     342           )
     343            break;
     344
     345        /* Race during dynamic load, restore and try again... */
     346        sigaction(SIGCHLD, &saOld2, NULL);
     347        RTThreadYield();
     348    }
     349#endif /* IPRT_USE_SIG_CHILD_DUMMY */
     350
    298351#ifdef IPRT_WITH_ALIGNMENT_CHECKS
    299352    /*
  • trunk/src/VBox/Runtime/r3/posix/process-posix.cpp

    r20498 r23869  
    110110    /*
    111111     * Spawn the child.
     112     *
     113     * HACK ALERT! Put the process into a new process group with pgid = pid
     114     * to make sure it differs from that of the parent process to ensure that
     115     * the IPRT waipit call doesn't race anyone (read XPCOM) doing group wide
     116     * waits.
    112117     */
    113118    pid_t pid;
     
    115120    if (!(fFlags & RTPROC_FLAGS_DAEMONIZE))
    116121    {
    117         /** @todo check if it requires any of those two attributes, don't remember atm. */
    118         rc = posix_spawn(&pid, pszExec, NULL, NULL, (char * const *)papszArgs,
    119                          (char * const *)papszEnv);
     122        posix_spawnattr_t Attr;
     123
     124        rc = posix_spawnattr_init(&Attr);
    120125        if (!rc)
    121126        {
    122             if (pProcess)
    123                 *pProcess = pid;
    124             return VINF_SUCCESS;
     127# ifndef RT_OS_OS2 /* We don't need this on OS/2 and I don't recall if it's actually implemented. */
     128            rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP);
     129            Assert(rc == 0);
     130            if (!rc)
     131            {
     132                rc = posix_spawnattr_setpgroup(&Attr, 0 /* pg == child pid */);
     133                Assert(rc == 0);
     134            }
     135# endif
     136            if (!rc)
     137            {
     138                /** @todo check if it requires any mandatory attributes or something, don't
     139                 *        remember atm. */
     140                rc = posix_spawn(&pid, pszExec, NULL, &Attr, (char * const *)papszArgs,
     141                                 (char * const *)papszEnv);
     142                if (!rc)
     143                {
     144                    int rc2 = posix_spawnattr_destroy(&Attr); Assert(rc2 == 0); NOREF(rc2);
     145                    if (pProcess)
     146                        *pProcess = pid;
     147                    return VINF_SUCCESS;
     148                }
     149            }
     150            int rc2 = posix_spawnattr_destroy(&Attr); Assert(rc2 == 0); NOREF(rc2);
    125151        }
    126152    }
     
    131157        if (!pid)
    132158        {
     159            setpgid(0, 0); /* see comment above */
     160
    133161            if (fFlags & RTPROC_FLAGS_DAEMONIZE)
    134162            {
  • trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxproces.c

    r23573 r23869  
    674674        while (1) {
    675675            do {
     676#ifdef VBOX
     677                /*
     678                 * make sure we wait only for child of our group
     679                 * to ensure we do not interfere with RT
     680                 */
     681                pid = waitpid((pid_t) 0, &status, 0);
     682#else
    676683                pid = waitpid((pid_t) -1, &status, 0);
     684#endif
    677685            } while ((pid_t) -1 == pid && EINTR == errno);
    678686
     
    764772        while (1) {
    765773            do {
     774#ifdef VBOX
     775                /*
     776                 * make sure we wait only for child of our group
     777                 * to ensure we do not interfere with RT
     778                 */
     779                pid = waitpid((pid_t) 0, &status, WNOHANG);
     780#else
    766781                pid = waitpid((pid_t) -1, &status, WNOHANG);
     782#endif
    767783            } while ((pid_t) -1 == pid && EINTR == errno);
    768784            if (0 == pid) break;
Note: See TracChangeset for help on using the changeset viewer.

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