VirtualBox

Changeset 102047 in vbox for trunk/src/libs/xpcom18a4/ipc


Ignore:
Timestamp:
Nov 9, 2023 6:27:01 PM (15 months ago)
Author:
vboxsync
Message:

libs/xpcom/ipc: Rewrote the IPC daemon startup code to use IPRT directly instead of NSPR, bugref:10545

Location:
trunk/src/libs/xpcom18a4/ipc/ipcd
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcdclient.cpp

    r101966 r102047  
    5656
    5757#include "prio.h"
    58 #include "prproces.h"
    5958
    6059#include <iprt/asm.h>
    6160#include <iprt/critsect.h>
     61#include <iprt/env.h>
     62#include <iprt/message.h>
     63#include <iprt/pipe.h>
     64#include <iprt/process.h>
     65#include <iprt/string.h>
    6266
    6367/* ------------------------------------------------------------------------- */
     
    12261230IPC_SpawnDaemon(const char *path)
    12271231{
    1228   PRFileDesc *readable = nsnull, *writable = nsnull;
    1229   PRProcessAttr *attr = nsnull;
    1230   nsresult rv = NS_ERROR_FAILURE;
    1231   PRFileDesc *devNull;
    1232   char *const argv[] = { (char *const) path, nsnull };
    1233   char c;
    1234 
    1235   // setup an anonymous pipe that we can use to determine when the daemon
    1236   // process has started up.  the daemon will write a char to the pipe, and
    1237   // when we read it, we'll know to proceed with trying to connect to the
    1238   // daemon.
    1239 
    1240   if (PR_CreatePipe(&readable, &writable) != PR_SUCCESS)
    1241     goto end;
    1242   PR_SetFDInheritable(writable, PR_TRUE);
    1243 
    1244   attr = PR_NewProcessAttr();
    1245   if (!attr)
    1246     goto end;
    1247 
    1248   if (PR_ProcessAttrSetInheritableFD(attr, writable, IPC_STARTUP_PIPE_NAME) != PR_SUCCESS)
    1249   goto end;
    1250 
    1251   devNull = PR_Open("/dev/null", PR_RDWR, 0);
    1252   if (!devNull)
    1253     goto end;
    1254 
    1255   PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, devNull);
    1256   PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, devNull);
    1257   PR_ProcessAttrSetStdioRedirect(attr, PR_StandardError, devNull);
    1258 
    1259   if (PR_CreateProcessDetached(path, argv, nsnull, attr) != PR_SUCCESS)
    1260     goto end;
    1261 
    1262   // Close /dev/null
    1263   PR_Close(devNull);
    1264   // close the child end of the pipe in order to get notification on unexpected
    1265   // child termination instead of being infinitely blocked in PR_Read().
    1266   PR_Close(writable);
    1267   writable = nsnull;
    1268 
    1269   if ((PR_Read(readable, &c, 1) != 1) || (c != IPC_STARTUP_PIPE_MAGIC))
    1270     goto end;
    1271 
    1272   rv = NS_OK;
    1273 end:
    1274   if (readable)
    1275     PR_Close(readable);
    1276   if (writable)
    1277     PR_Close(writable);
    1278   if (attr)
    1279     PR_DestroyProcessAttr(attr);
    1280   return rv;
     1232    /*
     1233     * Setup an anonymous pipe that we can use to determine when the daemon
     1234     * process has started up.  the daemon will write a char to the pipe, and
     1235     * when we read it, we'll know to proceed with trying to connect to the
     1236     * daemon.
     1237     */
     1238    RTPIPE hPipeWr = NIL_RTPIPE;
     1239    RTPIPE hPipeRd = NIL_RTPIPE;
     1240    int vrc = RTPipeCreate(&hPipeRd, &hPipeWr, RTPIPE_C_INHERIT_WRITE);
     1241    if (RT_SUCCESS(vrc))
     1242    {
     1243      char szPipeInheritFd[32]; RT_ZERO(szPipeInheritFd);
     1244      const char *const s_apszArgs[] = { (char *const) path, "--inherit-startup-pipe", &szPipeInheritFd[0], NULL };
     1245      char c;
     1246
     1247      ssize_t cch = RTStrFormatU32(&szPipeInheritFd[0], sizeof(szPipeInheritFd),
     1248                                   (uint32_t)RTPipeToNative(hPipeWr), 10 /*uiBase*/,
     1249                                   0 /*cchWidth*/, 0 /*cchPrecision*/, 0 /*fFlags*/);
     1250      Assert(cch > 0);
     1251
     1252      RTHANDLE hStdNil;
     1253      hStdNil.enmType = RTHANDLETYPE_FILE;
     1254      hStdNil.u.hFile = NIL_RTFILE;
     1255
     1256      vrc = RTProcCreateEx(path, s_apszArgs, RTENV_DEFAULT,
     1257                           RTPROC_FLAGS_DETACHED, &hStdNil, &hStdNil, &hStdNil,
     1258                           NULL /* pszAsUser */, NULL /* pszPassword */, NULL /* pExtraData */,
     1259                           NULL /* phProcess */);
     1260      if (RT_SUCCESS(vrc))
     1261      {
     1262          vrc = RTPipeClose(hPipeWr); AssertRC(vrc); RT_NOREF(vrc);
     1263          hPipeWr = NIL_RTPIPE;
     1264
     1265          uint8_t ch;
     1266          vrc = RTPipeReadBlocking(hPipeRd, &ch, sizeof(ch), NULL /*pcbRead*/);
     1267          if (   RT_SUCCESS(vrc)
     1268              && ch == IPC_STARTUP_PIPE_MAGIC)
     1269          {
     1270            RTPipeClose(hPipeRd);
     1271            return NS_OK;
     1272          }
     1273      }
     1274
     1275      if (hPipeWr != NIL_RTPIPE)
     1276          RTPipeClose(hPipeWr);
     1277      RTPipeClose(hPipeRd);
     1278    }
     1279
     1280    return NS_ERROR_FAILURE;
    12811281}
    12821282
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp

    r101996 r102047  
    4747
    4848#include <iprt/assert.h>
    49 
    50 //-----------------------------------------------------------------------------
    51 
    52 void
    53 IPC_NotifyParent()
    54 {
    55     PRFileDesc *fd = PR_GetInheritedFD(IPC_STARTUP_PIPE_NAME);
    56     if (fd) {
    57         char c = IPC_STARTUP_PIPE_MAGIC;
    58         PR_Write(fd, &c, 1);
    59         PR_Close(fd);
     49#include <iprt/errcore.h>
     50#include <iprt/pipe.h>
     51#include <VBox/log.h>
     52
     53//-----------------------------------------------------------------------------
     54
     55void
     56IPC_NotifyParent(uint32_t uPipeFd)
     57{
     58    if (uPipeFd != UINT32_MAX)
     59    {
     60        RTPIPE hPipe = NIL_RTPIPE;
     61        int vrc = RTPipeFromNative(&hPipe, (RTHCINTPTR)uPipeFd, RTPIPE_N_WRITE);
     62        if (RT_SUCCESS(vrc))
     63        {
     64            char c = IPC_STARTUP_PIPE_MAGIC;
     65
     66            vrc = RTPipeWriteBlocking(hPipe, &c, sizeof(c), NULL /*pcbWritten*/);
     67            AssertRC(vrc); RT_NOREF(vrc);
     68
     69            vrc = RTPipeClose(hPipe);
     70            AssertRC(vrc); RT_NOREF(vrc);
     71        }
    6072    }
    6173}
     
    110122        return IPC_PlatformSendMsg(client, msg);
    111123
    112     LOG(("  no registered message handler\n"));
     124    Log(("  no registered message handler\n"));
    113125    return PR_FAILURE;
    114126}
     
    117129IPC_NotifyClientUp(ipcClient *client)
    118130{
    119     LOG(("IPC_NotifyClientUp: clientID=%d\n", client->ID()));
     131    Log(("IPC_NotifyClientUp: clientID=%d\n", client->ID()));
    120132
    121133    for (int i=0; i<ipcClientCount; ++i) {
     
    129141IPC_NotifyClientDown(ipcClient *client)
    130142{
    131     LOG(("IPC_NotifyClientDown: clientID=%d\n", client->ID()));
     143    Log(("IPC_NotifyClientDown: clientID=%d\n", client->ID()));
    132144
    133145    for (int i=0; i<ipcClientCount; ++i) {
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h

    r39978 r102047  
    6161// notify parent that it can connect to the daemon.
    6262//
    63 void IPC_NotifyParent();
     63void IPC_NotifyParent(uint32_t uPipeFd);
    6464
    6565#endif // !ipcdPrivate_h__
  • trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp

    r101982 r102047  
    5050#endif
    5151
    52 #ifdef VBOX
    53 # include <iprt/initterm.h>
    54 #endif
     52#include <iprt/initterm.h>
     53#include <iprt/getopt.h>
     54#include <iprt/message.h>
    5555
    5656#include "prio.h"
     
    458458    PRNetAddr addr;
    459459
    460 #ifdef VBOX
    461460    /* Set up the runtime without loading the support driver. */
    462     RTR3InitExe(argc, &argv, 0);
    463 #endif
     461    int vrc = RTR3InitExe(argc, &argv, 0);
     462    if (RT_FAILURE(vrc))
     463        return RTMsgInitFailure(vrc);
     464
     465    /*
     466     * Parse the command line.
     467     */
     468    static RTGETOPTDEF const s_aOptions[] =
     469    {
     470        { "--inherit-startup-pipe", 'f', RTGETOPT_REQ_UINT32 },
     471        { "--socket-path",          'p', RTGETOPT_REQ_STRING },
     472    };
     473
     474    RTGETOPTSTATE State;
     475    vrc = RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1,  RTGETOPTINIT_FLAGS_OPTS_FIRST);
     476    if (RT_FAILURE(vrc))
     477        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOptInit failed: %Rrc", vrc);
     478
     479    uint32_t        uStartupPipeFd = UINT32_MAX;
     480    const char      *pszSocketPath = NULL;
     481    RTGETOPTUNION   ValueUnion;
     482    int             chOpt;
     483    while ((chOpt = RTGetOpt(&State, &ValueUnion)) != 0)
     484    {
     485        switch (chOpt)
     486        {
     487            case 'f':
     488                uStartupPipeFd = ValueUnion.u32;
     489                break;
     490            case 'p':
     491                pszSocketPath = ValueUnion.psz;
     492                break;
     493            default:
     494                return RTGetOptPrintError(chOpt, &ValueUnion);
     495        }
     496    }
    464497
    465498    //
     
    482515    // set socket address
    483516    addr.local.family = PR_AF_LOCAL;
    484     if (argc < 2)
     517    if (!pszSocketPath)
    485518        IPC_GetDefaultSocketPath(addr.local.path, sizeof(addr.local.path));
    486519    else
    487         PL_strncpyz(addr.local.path, argv[1], sizeof(addr.local.path));
     520        PL_strncpyz(addr.local.path, pszSocketPath, sizeof(addr.local.path));
    488521
    489522#ifdef IPC_USE_FILE_LOCK
     
    493526            LOG(("Another daemon is already running, exiting.\n"));
    494527            // send a signal to the blocked parent to indicate success
    495             IPC_NotifyParent();
     528            IPC_NotifyParent(uStartupPipeFd);
    496529            return 0;
    497530        }
     
    500533            // don't notify the parent to cause it to fail in PR_Read() after
    501534            // we terminate
    502 #ifdef VBOX
    503535            if (status != ELockFileOwner)
    504536                printf("Cannot create a lock file for '%s'.\n"
    505537                        "Check permissions.\n", addr.local.path);
    506 #endif
    507538            return 0;
    508539        }
     
    518549    }
    519550    else {
    520 #ifdef VBOX
    521551        // Use large backlog, as otherwise local sockets can reject connection
    522552        // attempts. Usually harmless, but causes an unnecessary start attempt
     
    524554        // usually succeeds. But better avoid unnecessary activities.
    525555        if (PR_Listen(listenFD, 128) != PR_SUCCESS) {
    526 #else /* !VBOX */
    527         if (PR_Listen(listenFD, 5) != PR_SUCCESS) {
    528 #endif /* !VBOX */
    529556            LOG(("PR_Listen failed [%d]\n", PR_GetError()));
    530557        }
    531558        else {
    532 #ifndef VBOX
    533             // redirect all standard file descriptors to /dev/null for
    534             // proper daemonizing
    535             PR_Close(PR_STDIN);
    536             PR_Open("/dev/null", O_RDONLY, 0);
    537             PR_Close(PR_STDOUT);
    538             PR_Open("/dev/null", O_WRONLY, 0);
    539             PR_Close(PR_STDERR);
    540             PR_Open("/dev/null", O_WRONLY, 0);
    541 #endif
    542 
    543             IPC_NotifyParent();
     559
     560            IPC_NotifyParent(uStartupPipeFd);
    544561
    545562#if defined(VBOX) && !defined(XP_OS2)
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