VirtualBox

Changeset 75807 in vbox


Ignore:
Timestamp:
Nov 29, 2018 7:09:21 AM (6 years ago)
Author:
vboxsync
Message:

VBoxGuestControl: Optimizing message handling - part 3. bugref:9313

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuestLib.h

    r75798 r75807  
    767767VBGLR3DECL(int) VbglR3GuestCtrlConnect(uint32_t *pidClient);
    768768VBGLR3DECL(int) VbglR3GuestCtrlDisconnect(uint32_t idClient);
     769VBGLR3DECL(bool) VbglR3GuestCtrlSupportsOptimizations(uint32_t idClient);
     770VBGLR3DECL(int) VbglR3GuestCtrlMakeMeMaster(uint32_t idClient);
    769771VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove);
    770772VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc);
    771773VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType,
    772774                                          void *pvPayload, uint32_t cbPayload);
     775VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient);
    773776VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId);
    774777VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters);
    775778VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(HGCMCLIENTID idClient);
    776779/* Guest session handling. */
     780VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey);
     781VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey);
     782VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession);
    777783VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t fFlags);
    778 VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, uint32_t uResult);
     784VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult);
    779785VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puProtocol, char *pszUser, uint32_t cbUser,
    780786                                              char *pszPassword, uint32_t  cbPassword, char *pszDomain, uint32_t cbDomain,
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp

    r75804 r75807  
    8383 *
    8484 * @returns VBox status code.
    85  * @param   uClientId       The client ID returned by VbglR3GuestCtrlConnect().
     85 * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
    8686 * @param   pidMsg          Where to store the message id.
    8787 * @param   pcParameters    Where to store the number  of parameters which will
    8888 *                          be received in a second call to the host.
    8989 */
    90 static int vbglR3GuestCtrlMsgWaitFor(uint32_t uClientId, uint32_t *pidMsg, uint32_t *pcParameters)
     90static int vbglR3GuestCtrlMsgWaitFor(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters)
    9191{
    9292    AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
     
    9494
    9595    HGCMMsgCmdWaitFor Msg;
    96     VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId,
     96    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
    9797                       GUEST_MSG_WAIT,      /* Tell the host we want our next command. */
    9898                       2);                  /* Just peek for the next message! */
     
    275275
    276276/**
     277 * Checks if the host supports the optimizes message and session functions.
     278 *
     279 * @returns true / false.
     280 * @param   idClient    The client ID returned by VbglR3GuestCtrlConnect().
     281 *                      We may need to use this for checking.
     282 * @since   6.0
     283 */
     284VBGLR3DECL(bool) VbglR3GuestCtrlSupportsOptimizations(uint32_t idClient)
     285{
     286    return vbglR3GuestCtrlSupportsPeekGetCancel(idClient);
     287}
     288
     289
     290/**
     291 * Make us the guest control master client.
     292 *
     293 * @returns VBox status code.
     294 * @param   idClient    The client ID returned by VbglR3GuestCtrlConnect().
     295 */
     296VBGLR3DECL(int) VbglR3GuestCtrlMakeMeMaster(uint32_t idClient)
     297{
     298    int rc;
     299    do
     300    {
     301        VBGLIOCHGCMCALL Hdr;
     302        VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MAKE_ME_MASTER, 0);
     303        rc = VbglR3HGCMCall(&Hdr, sizeof(Hdr));
     304    } while (rc == VERR_INTERRUPTED);
     305    return rc;
     306}
     307
     308
     309
     310/**
    277311 * Peeks at the next host message, waiting for one to turn up.
    278312 *
     
    299333        VbglHGCMParmUInt32Set(&Msg.num_parms, 0);
    300334        rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     335        LogRel(("VbglR3GuestCtrlMsgPeekWait -> %Rrc\n", rc));
    301336        if (RT_SUCCESS(rc))
    302337        {
     
    342377 *
    343378 * @return  IPRT status code.
    344  * @param   uClientId       The client ID returned by VbglR3GuestCtrlConnect().
     379 * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
    345380 * @param   uValue          The value to filter messages for.
    346381 * @param   uMaskAdd        Filter mask to add.
    347382 * @param   uMaskRemove     Filter mask to remove.
    348383 */
    349 VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove)
     384VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t idClient, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove)
    350385{
    351386    HGCMMsgCmdFilterSet Msg;
    352387
    353388    /* Tell the host we want to set a filter. */
    354     VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId, GUEST_MSG_FILTER_SET, 4);
     389    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_FILTER_SET, 4);
    355390    VbglHGCMParmUInt32Set(&Msg.value, uValue);
    356391    VbglHGCMParmUInt32Set(&Msg.mask_add, uMaskAdd);
     
    387422}
    388423
     424/**
     425 * Tell the host to skip the current message replying VERR_NOT_SUPPORTED
     426 *
     427 * @return  IPRT status code.
     428 * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
     429 */
     430VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient)
     431{
     432    if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
     433    {
     434        VBGLIOCHGCMCALL Hdr;
     435        VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MSG_SKIP, 0);
     436        return VbglR3HGCMCall(&Hdr, sizeof(Hdr));
     437    }
     438
     439    /* This is generally better than nothing... */
     440    return VbglR3GuestCtrlMsgSkipOld(idClient);
     441}
     442
    389443
    390444/**
     
    393447 *
    394448 * @return  IPRT status code.
    395  * @param   uClientId       The client ID returned by VbglR3GuestCtrlConnect().
    396  */
    397 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId)
     449 * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
     450 */
     451VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t idClient)
    398452{
    399453    HGCMMsgCmdSkip Msg;
    400454
    401455    /* Tell the host we want to skip the current assigned command. */
    402     VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId, GUEST_MSG_SKIP_OLD, 1);
     456    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_SKIP_OLD, 1);
    403457    VbglHGCMParmUInt32Set(&Msg.flags, 0 /* Flags, unused */);
    404458    return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     
    410464 *
    411465 * @returns VBox status code.
    412  * @param   uClientId     The client ID returned by VbglR3GuestCtrlConnect().
    413  */
    414 VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t uClientId)
     466 * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
     467 */
     468VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t idClient)
    415469{
    416470    HGCMMsgCancelPendingWaits Msg;
    417     VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientId, GUEST_MSG_CANCEL, 0);
     471    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_CANCEL, 0);
    418472    return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     473}
     474
     475
     476/**
     477 * Prepares a session.
     478 * @since   6.0
     479 * @sa      GUEST_SESSION_PREPARE
     480 */
     481VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
     482{
     483    int rc;
     484    do
     485    {
     486        struct
     487        {
     488            VBGLIOCHGCMCALL         Hdr;
     489            HGCMFunctionParameter   idSession;
     490            HGCMFunctionParameter   pKey;
     491        } Msg;
     492        VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_SESSION_PREPARE, 2);
     493        VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
     494        VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
     495        rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
     496    } while (rc == VERR_INTERRUPTED);
     497    return rc;
     498}
     499
     500
     501/**
     502 * Accepts a session.
     503 * @since   6.0
     504 * @sa      GUEST_SESSION_ACCEPT
     505 */
     506VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
     507{
     508    int rc;
     509    do
     510    {
     511        struct
     512        {
     513            VBGLIOCHGCMCALL         Hdr;
     514            HGCMFunctionParameter   idSession;
     515            HGCMFunctionParameter   pKey;
     516        } Msg;
     517        VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_SESSION_ACCEPT, 2);
     518        VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
     519        VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
     520        rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
     521    } while (rc == VERR_INTERRUPTED);
     522    return rc;
     523}
     524
     525
     526/**
     527 * Cancels a prepared session.
     528 * @since   6.0
     529 * @sa      GUEST_SESSION_CANCEL_PREPARED
     530 */
     531VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession)
     532{
     533    int rc;
     534    do
     535    {
     536        struct
     537        {
     538            VBGLIOCHGCMCALL         Hdr;
     539            HGCMFunctionParameter   idSession;
     540        } Msg;
     541        VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_SESSION_CANCEL_PREPARED, 1);
     542        VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
     543        rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
     544    } while (rc == VERR_INTERRUPTED);
     545    return rc;
    419546}
    420547
     
    442569
    443570
    444 VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, uint32_t uResult)
     571VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult)
    445572{
    446573    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    450577    VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
    451578    VbglHGCMParmUInt32Set(&Msg.type, uType);
    452     VbglHGCMParmUInt32Set(&Msg.result, uResult);
     579    VbglHGCMParmUInt32Set(&Msg.result, (uint32_t)iResult);
    453580
    454581    return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     
    497624                *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
    498625        }
     626        /* Try get the context ID so we can inform the host about this message retrival failure. */
     627        else if (Msg.context.u.value32 != HOST_SESSION_CREATE)
     628            Msg.context.GetUInt32(&pCtx->uContextID);
     629
    499630    } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
    500631    return rc;
     
    725856        HGCMMsgProcOutput Msg;
    726857        VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
    727         VbglHGCMParmUInt32Set(&Msg.context, 0);
     858        VbglHGCMParmUInt32Set(&Msg.context, HOST_EXEC_GET_OUTPUT);
    728859        VbglHGCMParmUInt32Set(&Msg.pid, 0);
    729860        VbglHGCMParmUInt32Set(&Msg.handle, 0);
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r75803 r75807  
    7777static uint64_t             g_idControlSession;
    7878/** The guest control service client ID. */
    79 static uint32_t             g_idControlSvcClient = 0;
     79uint32_t                    g_idControlSvcClient = 0;
    8080#if 0 /** @todo process limit */
    8181/** How many started guest processes are kept into memory for supplying
     
    9595 *  are kept in VBOXSERVICECTRLSESSIONTHREAD structures. */
    9696VBOXSERVICECTRLSESSION      g_Session;
     97/** Copy of VbglR3GuestCtrlSupportsOptimizations().*/
     98bool                        g_fControlSupportsOptimizations = true;
    9799
    98100
     
    190192    AssertRCReturn(rc, rc);
    191193
    192     VbglR3GetSessionId(&g_idControlSession);
    193     /* The status code is ignored as this information is not available with VBox < 3.2.10. */
    194 
     194    VbglR3GetSessionId(&g_idControlSession); /* The status code is ignored as this information is not available with VBox < 3.2.10. */
     195
     196    RTListInit(&g_lstControlSessionThreads);
     197
     198    /*
     199     * Try connect to the host service and tell it we want to be master (if supported).
     200     */
     201    rc = VbglR3GuestCtrlConnect(&g_idControlSvcClient);
    195202    if (RT_SUCCESS(rc))
    196         rc = VbglR3GuestCtrlConnect(&g_idControlSvcClient);
    197     if (RT_SUCCESS(rc))
    198     {
    199         VGSvcVerbose(3, "Guest control service client ID=%RU32\n", g_idControlSvcClient);
    200 
    201         /* Init session thread list. */
    202         RTListInit(&g_lstControlSessionThreads);
     203    {
     204        g_fControlSupportsOptimizations = VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient);
     205        if (g_fControlSupportsOptimizations)
     206            rc = VbglR3GuestCtrlMakeMeMaster(g_idControlSvcClient);
     207        if (RT_SUCCESS(rc))
     208        {
     209            VGSvcVerbose(3, "Guest control service client ID=%RU32%s\n",
     210                         g_idControlSvcClient, g_fControlSupportsOptimizations ? " w/ optimizations" : "");
     211            return VINF_SUCCESS;
     212        }
     213        VGSvcError("Failed to become guest control master: %Rrc\n", rc);
     214        VbglR3GuestCtrlDisconnect(g_idControlSvcClient);
    203215    }
    204216    else
     
    213225        else
    214226            VGSvcError("Failed to connect to the guest control service! Error: %Rrc\n", rc);
    215         RTSemEventMultiDestroy(g_hControlEvent);
    216         g_hControlEvent = NIL_RTSEMEVENTMULTI;
    217     }
     227    }
     228    RTSemEventMultiDestroy(g_hControlEvent);
     229    g_hControlEvent      = NIL_RTSEMEVENTMULTI;
     230    g_idControlSvcClient = 0;
    218231    return rc;
    219232}
     
    226239{
    227240    /*
    228      * Tell the control thread that it can continue
    229      * spawning services.
     241     * Tell the control thread that it can continue spawning services.
    230242     */
    231243    RTThreadUserSignal(RTThreadSelf());
     
    239251    AssertReturn(pvScratchBuf, VERR_NO_MEMORY);
    240252
    241     VBGLR3GUESTCTRLCMDCTX ctxHost = { g_idControlSvcClient };
    242     /* Set default protocol version to 1. */
    243     ctxHost.uProtocol = 1;
     253    VBGLR3GUESTCTRLCMDCTX ctxHost = { g_idControlSvcClient, 0 /*idContext*/, 2 /*uProtocol*/, 0  /*cParms*/ };
    244254
    245255    int rc = VINF_SUCCESS;      /* (shut up compiler warnings) */
     
    288298                    break;
    289299
     300                /* This message is also sent to the child session process (by the host). */
    290301                case HOST_SESSION_CLOSE:
    291302                    rc = vgsvcGstCtrlHandleSessionClose(&ctxHost);
     
    293304
    294305                default:
    295                 {
    296                     /*
    297                      * Protocol v1 did not have support for (dedicated)
    298                      * guest sessions, so all actions need to be performed
    299                      * under behalf of VBoxService's main executable.
    300                      *
    301                      * The global session object then acts as a host for all
    302                      * started guest processes which bring all their
    303                      * credentials with them with the actual guest process
    304                      * execution call.
    305                      */
    306                     if (ctxHost.uProtocol == 1)
    307                         rc = VGSvcGstCtrlSessionHandler(&g_Session, idMsg, &ctxHost, pvScratchBuf, cbScratchBuf, pfShutdown);
     306                    if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient))
     307                    {
     308                        rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient);
     309                        VGSvcVerbose(1, "Skipped unexpected message idMsg=%RU32 (%s), cParms=%RU32 (rc=%Rrc)\n",
     310                                     idMsg, GstCtrlHostFnName((eHostFn)idMsg), cParms, rc);
     311                    }
    308312                    else
    309313                    {
    310                         /*
    311                          * ... on newer protocols handling all other commands is
    312                          * up to the guest session fork of VBoxService, so just
    313                          * skip all not wanted messages here.
    314                          */
    315314                        rc = VbglR3GuestCtrlMsgSkipOld(g_idControlSvcClient);
    316                         VGSvcVerbose(3, "Skipping idMsg=%RU32, cParms=%RU32, rc=%Rrc\n", idMsg, cParms, rc);
     315                        VGSvcVerbose(3, "Skipped idMsg=%RU32, cParms=%RU32, rc=%Rrc\n", idMsg, cParms, rc);
    317316                    }
    318317                    break;
    319                 }
    320318            }
    321319
     
    387385    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    388386
     387    /*
     388     * Retrieve the message parameters.
     389     */
    389390    VBOXSERVICECTRLSESSIONSTARTUPINFO ssInfo = { 0 };
    390391    int rc = VbglR3GuestCtrlSessionGetOpen(pHostCtx,
     
    396397    if (RT_SUCCESS(rc))
    397398    {
    398         /* The session open call has the protocol version the host
    399          * wants to use. So update the current protocol version with the one the
    400          * host wants to use in subsequent calls. */
    401         pHostCtx->uProtocol = ssInfo.uProtocol;
    402         VGSvcVerbose(3, "Client ID=%RU32 now is using protocol %RU32\n", pHostCtx->uClientID, pHostCtx->uProtocol);
    403 
    404         rc = VGSvcGstCtrlSessionThreadCreate(&g_lstControlSessionThreads, &ssInfo, NULL /* ppSessionThread */);
    405     }
    406 
    407     if (RT_FAILURE(rc))
    408     {
    409         /* Report back on failure. On success this will be done
    410          * by the forked session thread. */
    411         int rc2 = VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc /* uint32_t vs. int */);
    412         if (RT_FAILURE(rc2))
    413             VGSvcError("Reporting session error status on open failed with rc=%Rrc\n", rc2);
    414     }
    415 
     399        /*
     400         * Flat out refuse to work with protocol v1 hosts.
     401         */
     402        if (ssInfo.uProtocol == 2)
     403        {
     404            pHostCtx->uProtocol = ssInfo.uProtocol;
     405            VGSvcVerbose(3, "Client ID=%RU32 now is using protocol %RU32\n", pHostCtx->uClientID, pHostCtx->uProtocol);
     406
     407/** @todo Someone explain why this code isn't in this file too?  v1 support? */
     408            rc = VGSvcGstCtrlSessionThreadCreate(&g_lstControlSessionThreads, &ssInfo, NULL /* ppSessionThread */);
     409            /* Report failures to the host (successes are taken care of by the session thread). */
     410        }
     411        else
     412        {
     413            VGSvcError("The host wants to use protocol v%u, we only support v2!\n", ssInfo.uProtocol);
     414            rc = VERR_VERSION_MISMATCH;
     415        }
     416        if (RT_FAILURE(rc))
     417        {
     418            int rc2 = VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc);
     419            if (RT_FAILURE(rc2))
     420                VGSvcError("Reporting session error status on open failed with rc=%Rrc\n", rc2);
     421        }
     422    }
     423    /*
     424     * If we cannot retrieve the message, make sure to skip the command.
     425     *
     426     * Note! If we totally failed to get any valid context ID, the host will
     427     *       not see the notification and be stuck till it times out.
     428     */
     429    else
     430    {
     431        VGSvcError("Error fetching guest session parameters: %Rrc\n", rc);
     432        VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc);
     433        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID);
     434    }
    416435    VGSvcVerbose(3, "Opening a new guest session returned rc=%Rrc\n", rc);
    417436    return rc;
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h

    r70390 r75807  
    9999    RTLISTNODE                      Node;
    100100    /** The sessions's startup info. */
    101     VBOXSERVICECTRLSESSIONSTARTUPINFO
    102                                     StartupInfo;
     101    VBOXSERVICECTRLSESSIONSTARTUPINFO StartupInfo;
     102    /** Critical section for thread-safe use. */
     103    RTCRITSECT                      CritSect;
    103104    /** The worker thread. */
    104105    RTTHREAD                        Thread;
    105     /** Critical section for thread-safe use. */
    106     RTCRITSECT                      CritSect;
    107106    /** Process handle for forked child. */
    108107    RTPROCESS                       hProcess;
     
    133132    RTPIPE                          hNotificationPipeR;
    134133#endif
     134    /** Pipe for handing the secret key to the session process. */
     135    RTPIPE                          hKeyPipe;
     136    /** Secret key. */
     137    uint8_t                         abKey[_4K];
    135138} VBOXSERVICECTRLSESSIONTHREAD;
    136139/** Pointer to thread data. */
     
    289292extern RTLISTANCHOR             g_lstControlSessionThreads;
    290293extern VBOXSERVICECTRLSESSION   g_Session;
     294extern uint32_t                 g_idControlSvcClient;
     295extern bool                     g_fControlSupportsOptimizations;
    291296
    292297
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp

    r70390 r75807  
    14601460                 pProcess->StartupInfo.szCmd, pProcess->uClientID, pProcess->StartupInfo.uFlags);
    14611461
    1462     /* The process thread is not interested in receiving any commands;
    1463      * tell the host service. */
    1464     rc = VbglR3GuestCtrlMsgFilterSet(pProcess->uClientID, 0 /* Skip all */,
    1465                                      0 /* Filter mask to add */, 0 /* Filter mask to remove */);
    1466     if (RT_FAILURE(rc))
    1467     {
    1468         VGSvcError("Unable to set message filter, rc=%Rrc\n", rc);
    1469         /* Non-critical. */
     1462    /* Legacy setting: */
     1463    if (!VbglR3GuestCtrlSupportsOptimizations(pProcess->uClientID))
     1464    {
     1465        rc = VbglR3GuestCtrlMsgFilterSet(pProcess->uClientID, 0 /* Skip all */,
     1466                                         0 /* Filter mask to add */, 0 /* Filter mask to remove */);
     1467        if (RT_FAILURE(rc))
     1468            VGSvcError("Unable to set message filter, rc=%Rrc\n", rc); /* Non-critical. */
    14701469    }
    14711470
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r75798 r75807  
    3333#include <iprt/poll.h>
    3434#include <iprt/process.h>
     35#include <iprt/rand.h>
    3536
    3637#include "VBoxServiceInternal.h"
     
    11151116/**
    11161117 * Thread main routine for a spawned guest session process.
     1118 *
    11171119 * This thread runs in the main executable to control the spawned session process.
    11181120 *
     
    11271129    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    11281130
    1129     uint32_t uSessionID = pThread->StartupInfo.uSessionID;
    1130 
    1131     uint32_t idClient;
    1132     int rc = VbglR3GuestCtrlConnect(&idClient);
    1133     if (RT_SUCCESS(rc))
    1134     {
    1135         VGSvcVerbose(3, "Session ID=%RU32 thread running, client ID=%RU32\n", uSessionID, idClient);
    1136 
    1137         /* The session thread is not interested in receiving any commands;
    1138          * tell the host service. */
    1139         rc = VbglR3GuestCtrlMsgFilterSet(idClient, 0 /* Skip all */, 0 /* Filter mask to add */, 0 /* Filter mask to remove */);
    1140         if (RT_FAILURE(rc))
    1141         {
    1142             VGSvcError("Unable to set message filter, rc=%Rrc\n", rc);
    1143             /* Non-critical. */
    1144             rc = VINF_SUCCESS;
    1145         }
    1146     }
    1147     else
    1148         VGSvcError("Error connecting to guest control service, rc=%Rrc\n", rc);
    1149 
    1150     if (RT_FAILURE(rc))
    1151         pThread->fShutdown = true;
     1131    uint32_t const idSession = pThread->StartupInfo.uSessionID;
     1132    uint32_t const idClient  = g_idControlSvcClient;
     1133    VGSvcVerbose(3, "Session ID=%RU32 thread running\n", idSession);
    11521134
    11531135    /* Let caller know that we're done initializing, regardless of the result. */
     
    11551137    AssertRC(rc2);
    11561138
    1157     if (RT_FAILURE(rc))
    1158         return rc;
    1159 
    1160     bool fProcessAlive = true;
    1161     RTPROCSTATUS ProcessStatus;
    1162     RT_ZERO(ProcessStatus);
    1163 
    1164     int rcWait;
    1165     uint32_t uTimeoutsMS = 30 * 1000; /** @todo Make this configurable. Later. */
    1166     uint64_t u64TimeoutStart = 0;
    1167 
     1139    /*
     1140     * Wait for the child process to stop or the shutdown flag to be signalled.
     1141     */
     1142    RTPROCSTATUS    ProcessStatus       = { 0, RTPROCEXITREASON_NORMAL };
     1143    bool            fProcessAlive       = true;
     1144    bool            fSessionCancelled   = VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient);
     1145    uint32_t        cMsShutdownTimeout  = 30 * 1000; /** @todo Make this configurable. Later. */
     1146    uint64_t        msShutdownStart     = 0;
     1147    uint64_t const  msStart             = RTTimeMilliTS();
     1148    size_t          offSecretKey        = 0;
     1149    int             rcWait;
    11681150    for (;;)
    11691151    {
     1152        /* Secret key feeding. */
     1153        if (offSecretKey < sizeof(pThread->abKey))
     1154        {
     1155            size_t cbWritten = 0;
     1156            rc2 = RTPipeWrite(pThread->hKeyPipe, &pThread->abKey[offSecretKey], sizeof(pThread->abKey) - offSecretKey, &cbWritten);
     1157            if (RT_SUCCESS(rc2))
     1158                offSecretKey += cbWritten;
     1159        }
     1160
     1161        /* Poll child process status. */
    11701162        rcWait = RTProcWaitNoResume(pThread->hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus);
    11711163        if (   rcWait == VINF_SUCCESS
     
    11781170                       ("Got unexpected rc=%Rrc while waiting for session process termination\n", rcWait));
    11791171
     1172        /* Shutting down? */
    11801173        if (ASMAtomicReadBool(&pThread->fShutdown))
    11811174        {
    1182             if (!u64TimeoutStart)
     1175            if (!msShutdownStart)
    11831176            {
    11841177                VGSvcVerbose(3, "Notifying guest session process (PID=%RU32, session ID=%RU32) ...\n",
    1185                              pThread->hProcess, uSessionID);
     1178                             pThread->hProcess, idSession);
    11861179
    11871180                VBGLR3GUESTCTRLCMDCTX hostCtx =
    11881181                {
    11891182                    /* .idClient  = */  idClient,
    1190                     /* .idContext = */  VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(uSessionID),
     1183                    /* .idContext = */  VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(idSession),
    11911184                    /* .uProtocol = */  pThread->StartupInfo.uProtocol,
    11921185                    /* .cParams   = */  2
    11931186                };
    1194                 rc = VbglR3GuestCtrlSessionClose(&hostCtx, 0 /* fFlags */);
    1195                 if (RT_FAILURE(rc))
     1187                rc2 = VbglR3GuestCtrlSessionClose(&hostCtx, 0 /* fFlags */);
     1188                if (RT_FAILURE(rc2))
    11961189                {
    11971190                    VGSvcError("Unable to notify guest session process (PID=%RU32, session ID=%RU32), rc=%Rrc\n",
    1198                                pThread->hProcess, uSessionID, rc);
    1199 
    1200                     if (rc == VERR_NOT_SUPPORTED)
     1191                               pThread->hProcess, idSession, rc2);
     1192
     1193                    if (rc2 == VERR_NOT_SUPPORTED)
    12011194                    {
    12021195                        /* Terminate guest session process in case it's not supported by a too old host. */
    1203                         rc = RTProcTerminate(pThread->hProcess);
     1196                        rc2 = RTProcTerminate(pThread->hProcess);
    12041197                        VGSvcVerbose(3, "Terminating guest session process (PID=%RU32) ended with rc=%Rrc\n",
    1205                                      pThread->hProcess, rc);
     1198                                     pThread->hProcess, rc2);
    12061199                    }
    12071200                    break;
    12081201                }
    12091202
    1210                 VGSvcVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit (%RU32ms timeout) ...\n",
    1211                              uSessionID, uTimeoutsMS);
    1212                 u64TimeoutStart = RTTimeMilliTS();
     1203                VGSvcVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit (%RU32 ms timeout) ...\n",
     1204                             idSession, cMsShutdownTimeout);
     1205                msShutdownStart = RTTimeMilliTS();
    12131206                continue; /* Don't waste time on waiting. */
    12141207            }
    1215             if (RTTimeMilliTS() - u64TimeoutStart > uTimeoutsMS)
     1208            if (RTTimeMilliTS() - msShutdownStart > cMsShutdownTimeout)
    12161209            {
    1217                  VGSvcVerbose(3, "Guest session ID=%RU32 process did not shut down within time\n", uSessionID);
     1210                 VGSvcVerbose(3, "Guest session ID=%RU32 process did not shut down within time\n", idSession);
    12181211                 break;
    12191212            }
    12201213        }
    12211214
     1215        /* Cancel the prepared session stuff after 30 seconds. */
     1216        if (  !fSessionCancelled
     1217            && RTTimeMilliTS() - msStart >= 30000)
     1218        {
     1219            VbglR3GuestCtrlSessionCancelPrepared(g_idControlSvcClient, idSession);
     1220            fSessionCancelled = true;
     1221        }
     1222
     1223/** @todo r=bird: This 100ms sleep is _extremely_ sucky! */
    12221224        RTThreadSleep(100); /* Wait a bit. */
    12231225    }
    12241226
     1227    if (!fSessionCancelled)
     1228        VbglR3GuestCtrlSessionCancelPrepared(g_idControlSvcClient, idSession);
     1229
    12251230    if (!fProcessAlive)
    12261231    {
    12271232        VGSvcVerbose(2, "Guest session process (ID=%RU32) terminated with rc=%Rrc, reason=%d, status=%d\n",
    1228                      uSessionID, rcWait, ProcessStatus.enmReason, ProcessStatus.iStatus);
     1233                     idSession, rcWait, ProcessStatus.enmReason, ProcessStatus.iStatus);
    12291234        if (ProcessStatus.iStatus == RTEXITCODE_INIT)
    12301235        {
    1231             VGSvcError("Guest session process (ID=%RU32) failed to initialize. Here some hints:\n", uSessionID);
     1236            VGSvcError("Guest session process (ID=%RU32) failed to initialize. Here some hints:\n", idSession);
    12321237            VGSvcError("- Is logging enabled and the output directory is read-only by the guest session user?\n");
    12331238            /** @todo Add more here. */
     
    12421247        for (int i = 0; i < 3; i++)
    12431248        {
    1244             VGSvcVerbose(2, "Guest session ID=%RU32 process still alive, killing attempt %d/3\n", uSessionID, i + 1);
    1245 
    1246             rc = RTProcTerminate(pThread->hProcess);
    1247             if (RT_SUCCESS(rc))
     1249            VGSvcVerbose(2, "Guest session ID=%RU32 process still alive, killing attempt %d/3\n", idSession, i + 1);
     1250
     1251            rc2 = RTProcTerminate(pThread->hProcess);
     1252            if (RT_SUCCESS(rc2))
    12481253                break;
    12491254            /** @todo r=bird: What's the point of sleeping 3 second after the last attempt? */
     
    12511256        }
    12521257
    1253         VGSvcVerbose(2, "Guest session ID=%RU32 process termination resulted in rc=%Rrc\n", uSessionID, rc);
    1254 
    1255         uSessionStatus = RT_SUCCESS(rc) ? GUEST_SESSION_NOTIFYTYPE_TOK : GUEST_SESSION_NOTIFYTYPE_TOA;
     1258        VGSvcVerbose(2, "Guest session ID=%RU32 process termination resulted in rc=%Rrc\n", idSession, rc2);
     1259        uSessionStatus = RT_SUCCESS(rc2) ? GUEST_SESSION_NOTIFYTYPE_TOK : GUEST_SESSION_NOTIFYTYPE_TOA;
    12561260    }
    12571261    else if (RT_SUCCESS(rcWait))
     
    12791283    else
    12801284    {
    1281         /* If we didn't find the guest process anymore, just assume it
    1282          * terminated normally. */
     1285        /* If we didn't find the guest process anymore, just assume it terminated normally. */
    12831286        uSessionStatus = GUEST_SESSION_NOTIFYTYPE_TEN;
    12841287    }
    12851288
    12861289    VGSvcVerbose(3, "Guest session ID=%RU32 thread ended with sessionStatus=%RU32, sessionRc=%Rrc\n",
    1287                  uSessionID, uSessionStatus, uSessionRc);
    1288 
    1289     /* Report final status. */
     1290                 idSession, uSessionStatus, uSessionRc);
     1291
     1292    /*
     1293     * Report final status.
     1294     */
    12901295    Assert(uSessionStatus != GUEST_SESSION_NOTIFYTYPE_UNDEFINED);
    1291     VBGLR3GUESTCTRLCMDCTX ctx = { idClient, VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(uSessionID) };
     1296    VBGLR3GUESTCTRLCMDCTX ctx = { idClient, VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(idSession) };
    12921297    rc2 = VbglR3GuestCtrlSessionNotify(&ctx, uSessionStatus, uSessionRc);
    12931298    if (RT_FAILURE(rc2))
    1294         VGSvcError("Reporting session ID=%RU32 final status failed with rc=%Rrc\n", uSessionID, rc2);
    1295 
    1296     VbglR3GuestCtrlDisconnect(idClient);
    1297 
    1298     VGSvcVerbose(3, "Session ID=%RU32 thread ended with rc=%Rrc\n", uSessionID, rc);
    1299     return rc;
    1300 }
    1301 
     1299        VGSvcError("Reporting session ID=%RU32 final status failed with rc=%Rrc\n", idSession, rc2);
     1300
     1301    VGSvcVerbose(3, "Session ID=%RU32 thread ending\n", idSession);
     1302    return VINF_SUCCESS;
     1303}
     1304
     1305/**
     1306 * Reads the secret key the parent VBoxService instance passed us and pass it
     1307 * along as a authentication token to the host service.
     1308 *
     1309 * For older hosts, this sets up the message filtering.
     1310 *
     1311 * @returns VBox status code.
     1312 * @param   idClient        The HGCM client ID.
     1313 * @param   idSession       The session ID.
     1314 */
     1315static int vgsvcGstCtrlSessionReadKeyAndAccept(uint32_t idClient, uint32_t idSession)
     1316{
     1317    /*
     1318     * Read it.
     1319     */
     1320    RTHANDLE Handle;
     1321    int rc = RTHandleGetStandard(RTHANDLESTD_INPUT, &Handle);
     1322    if (RT_SUCCESS(rc))
     1323    {
     1324        if (Handle.enmType == RTHANDLETYPE_PIPE)
     1325        {
     1326            uint8_t abSecretKey[RT_SIZEOFMEMB(VBOXSERVICECTRLSESSIONTHREAD, abKey)];
     1327            rc = RTPipeReadBlocking(Handle.u.hPipe, abSecretKey, sizeof(abSecretKey), NULL);
     1328            if (RT_SUCCESS(rc))
     1329            {
     1330                VGSvcVerbose(3, "Got secret key from standard input.\n");
     1331
     1332                /*
     1333                 * Do the accepting, if appropriate.
     1334                 */
     1335                if (g_fControlSupportsOptimizations)
     1336                {
     1337                    rc = VbglR3GuestCtrlSessionAccept(idClient, idSession, abSecretKey, sizeof(abSecretKey));
     1338                    if (RT_SUCCESS(rc))
     1339                        VGSvcVerbose(3, "Session %u accepted\n");
     1340                    else
     1341                        VGSvcError("Failed to accept session: %Rrc\n", rc);
     1342                }
     1343                else
     1344                {
     1345                    /* For legacy hosts, we do the filtering thingy. */
     1346                    rc = VbglR3GuestCtrlMsgFilterSet(idClient, VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(idSession),
     1347                                                     VBOX_GUESTCTRL_FILTER_BY_SESSION(idSession), 0);
     1348                    if (RT_SUCCESS(rc))
     1349                        VGSvcVerbose(3, "Session %u filtering successfully enabled\n");
     1350                    else
     1351                        VGSvcError("Failed to set session filter: %Rrc\n", rc);
     1352                }
     1353            }
     1354            else
     1355                VGSvcError("Error reading secret key from standard input: %Rrc\n", rc);
     1356        }
     1357        else
     1358        {
     1359            VGSvcError("Standard input is not a pipe!\n");
     1360            rc = VERR_INVALID_HANDLE;
     1361        }
     1362        RTHandleClose(&Handle);
     1363    }
     1364    else
     1365        VGSvcError("RTHandleGetStandard failed on standard input: %Rrc\n", rc);
     1366    return rc;
     1367}
    13021368
    13031369/**
     
    13201386    if (RT_FAILURE(rc))
    13211387        return VGSvcError("Error connecting to guest control service, rc=%Rrc\n", rc);
    1322 
    1323     /*
    1324      * Set session filter. This prevents the guest control host service from
    1325      * sending messages which belong to another session we don't want to handle.
    1326      *
    1327      * Note! Earlier versions of this code would issue GUEST_SESSION_NOTIFYTYPE_STARTED
    1328      *       even if this failed, then shutdown after that.  Since there was no
    1329      *       comments explain why, I (bird) assume is was an unintentional glitch.
    1330      *
    1331      * Note! There was also a fSessionFilter being set on VERR_NOT_SUPPORTED here
    1332      *       but since it wasn't used, I assume it was just a leftover from some
    1333      *       earlier workaround for host behaviour/whatever...
    1334      */
    1335 /** @todo r=bird: Unless the host is filtering out everything by default, there
    1336  * is a ugly race here between the client masking unwanted messages and the host
    1337  * pushing more messages to the clients.  We could in theory end up with someone
    1338  * elses' messages as the first ones.  Too late to require a VbglR3GuestCtrlMsgFilterSet
    1339  * call by all clients, which is what would've made sense...  I guess
    1340  * VbglR3GuestCtrlSessionNotify can't be used as a green-light for sending messages
    1341  * either. */
    1342     uint32_t uFilterAdd = VBOX_GUESTCTRL_FILTER_BY_SESSION(pSession->StartupInfo.uSessionID);
    1343     rc = VbglR3GuestCtrlMsgFilterSet(idClient,
    1344                                      VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(pSession->StartupInfo.uSessionID),
    1345                                      uFilterAdd, 0 /* Filter remove */);
    1346     VGSvcVerbose(3, "Setting message filterAdd=0x%x returned %Rrc\n", uFilterAdd, rc);
    1347     if (   RT_SUCCESS(rc)
    1348         || rc == VERR_NOT_SUPPORTED /* No session filter available. Ignore. */ )
     1388    g_fControlSupportsOptimizations = VbglR3GuestCtrlSupportsOptimizations(idClient);
     1389
     1390    rc = vgsvcGstCtrlSessionReadKeyAndAccept(idClient, pSession->StartupInfo.uSessionID);
     1391    if (RT_SUCCESS(rc))
    13491392    {
    13501393        VGSvcVerbose(1, "Using client ID=%RU32\n", idClient);
     
    13771420                    uint32_t cParms = 0;
    13781421                    rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &cParms);
    1379                     if (   RT_SUCCESS(rc)
    1380                         || rc == VERR_TOO_MUCH_DATA)
     1422                    if (RT_SUCCESS(rc))
    13811423                    {
    13821424                        VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, cParms, rc);
     
    17151757 * Creates the process for a guest session.
    17161758 *
    1717  *
    17181759 * @return  VBox status code.
    17191760 * @param   pSessionStartupInfo     Session startup info.
     
    17601801     * Start by assembling the argument list.
    17611802     */
    1762     int  rc = VINF_SUCCESS;
    17631803    char szExeName[RTPATH_MAX];
    17641804    char *pszExeName = RTProcGetExecutablePath(szExeName, sizeof(szExeName));
    1765     if (pszExeName)
    1766     {
    1767         char szParmSessionID[32];
    1768         RTStrPrintf(szParmSessionID, sizeof(szParmSessionID), "--session-id=%RU32", pSessionThread->StartupInfo.uSessionID);
    1769 
    1770         char szParmSessionProto[32];
    1771         RTStrPrintf(szParmSessionProto, sizeof(szParmSessionProto), "--session-proto=%RU32",
    1772                     pSessionThread->StartupInfo.uProtocol);
     1805    AssertReturn(pszExeName, VERR_FILENAME_TOO_LONG);
     1806
     1807    char szParmSessionID[32];
     1808    RTStrPrintf(szParmSessionID, sizeof(szParmSessionID), "--session-id=%RU32", pSessionThread->StartupInfo.uSessionID);
     1809
     1810    char szParmSessionProto[32];
     1811    RTStrPrintf(szParmSessionProto, sizeof(szParmSessionProto), "--session-proto=%RU32",
     1812                pSessionThread->StartupInfo.uProtocol);
    17731813#ifdef DEBUG
    1774         char szParmThreadId[32];
    1775         RTStrPrintf(szParmThreadId, sizeof(szParmThreadId), "--thread-id=%RU32", uCtrlSessionThread);
    1776 #endif
    1777         unsigned    idxArg = 0; /* Next index in argument vector. */
    1778         char const *apszArgs[24];
    1779 
    1780         apszArgs[idxArg++] = pszExeName;
    1781         apszArgs[idxArg++] = "guestsession";
    1782         apszArgs[idxArg++] = szParmSessionID;
    1783         apszArgs[idxArg++] = szParmSessionProto;
     1814    char szParmThreadId[32];
     1815    RTStrPrintf(szParmThreadId, sizeof(szParmThreadId), "--thread-id=%RU32", uCtrlSessionThread);
     1816#endif
     1817    unsigned    idxArg = 0; /* Next index in argument vector. */
     1818    char const *apszArgs[24];
     1819
     1820    apszArgs[idxArg++] = pszExeName;
     1821    apszArgs[idxArg++] = "guestsession";
     1822    apszArgs[idxArg++] = szParmSessionID;
     1823    apszArgs[idxArg++] = szParmSessionProto;
    17841824#ifdef DEBUG
    1785         apszArgs[idxArg++] = szParmThreadId;
    1786 #endif
    1787         if (!fAnonymous) /* Do we need to pass a user name? */
    1788         {
    1789             apszArgs[idxArg++] = "--user";
    1790             apszArgs[idxArg++] = pSessionThread->StartupInfo.szUser;
    1791 
    1792             if (strlen(pSessionThread->StartupInfo.szDomain))
     1825    apszArgs[idxArg++] = szParmThreadId;
     1826#endif
     1827    if (!fAnonymous) /* Do we need to pass a user name? */
     1828    {
     1829        apszArgs[idxArg++] = "--user";
     1830        apszArgs[idxArg++] = pSessionThread->StartupInfo.szUser;
     1831
     1832        if (strlen(pSessionThread->StartupInfo.szDomain))
     1833        {
     1834            apszArgs[idxArg++] = "--domain";
     1835            apszArgs[idxArg++] = pSessionThread->StartupInfo.szDomain;
     1836        }
     1837    }
     1838
     1839    /* Add same verbose flags as parent process. */
     1840    char szParmVerbose[32];
     1841    if (g_cVerbosity > 0)
     1842    {
     1843        unsigned cVs = RT_MIN(g_cVerbosity, RT_ELEMENTS(szParmVerbose) - 2);
     1844        szParmVerbose[0] = '-';
     1845        memset(&szParmVerbose[1], 'v', cVs);
     1846        szParmVerbose[1 + cVs] = '\0';
     1847        apszArgs[idxArg++] = szParmVerbose;
     1848    }
     1849
     1850    /* Add log file handling. Each session will have an own
     1851     * log file, naming based on the parent log file. */
     1852    char szParmLogFile[sizeof(g_szLogFile) + 128];
     1853    if (g_szLogFile[0])
     1854    {
     1855        const char *pszSuffix = RTPathSuffix(g_szLogFile);
     1856        if (!pszSuffix)
     1857            pszSuffix = strchr(g_szLogFile, '\0');
     1858        size_t cchBase = pszSuffix - g_szLogFile;
     1859#ifndef DEBUG
     1860        RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%s%s",
     1861                    cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, pSessionStartupInfo->szUser, pszSuffix);
     1862#else
     1863        RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%RU32-%s%s",
     1864                    cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, uCtrlSessionThread,
     1865                    pSessionStartupInfo->szUser, pszSuffix);
     1866#endif
     1867        apszArgs[idxArg++] = "--logfile";
     1868        apszArgs[idxArg++] = szParmLogFile;
     1869    }
     1870
     1871#ifdef DEBUG
     1872    if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDOUT)
     1873        apszArgs[idxArg++] = "--dump-stdout";
     1874    if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDERR)
     1875        apszArgs[idxArg++] = "--dump-stderr";
     1876#endif
     1877    apszArgs[idxArg] = NULL;
     1878    Assert(idxArg < RT_ELEMENTS(apszArgs));
     1879
     1880    if (g_cVerbosity > 3)
     1881    {
     1882        VGSvcVerbose(4, "Spawning parameters:\n");
     1883        for (idxArg = 0; apszArgs[idxArg]; idxArg++)
     1884            VGSvcVerbose(4, "\t%s\n", apszArgs[idxArg]);
     1885    }
     1886
     1887    /*
     1888     * Flags.
     1889     */
     1890    uint32_t const fProcCreate = RTPROC_FLAGS_PROFILE
     1891#ifdef RT_OS_WINDOWS
     1892                               | RTPROC_FLAGS_SERVICE
     1893                               | RTPROC_FLAGS_HIDDEN
     1894#endif
     1895                               ;
     1896
     1897    /*
     1898     * Configure standard handles.
     1899     */
     1900    RTHANDLE hStdIn;
     1901    int rc = RTPipeCreate(&hStdIn.u.hPipe, &pSessionThread->hKeyPipe, RTPIPE_C_INHERIT_READ);
     1902    if (RT_SUCCESS(rc))
     1903    {
     1904        hStdIn.enmType = RTHANDLETYPE_PIPE;
     1905
     1906        RTHANDLE hStdOutAndErr;
     1907        rc = RTFileOpenBitBucket(&hStdOutAndErr.u.hFile, RTFILE_O_WRITE);
     1908        if (RT_SUCCESS(rc))
     1909        {
     1910            hStdOutAndErr.enmType = RTHANDLETYPE_FILE;
     1911
     1912            /*
     1913             * Windows: If a domain name is given, construct an UPN (User Principle Name)
     1914             *          with the domain name built-in, e.g. "[email protected]".
     1915             */
     1916            const char *pszUser    = pSessionThread->StartupInfo.szUser;
     1917#ifdef RT_OS_WINDOWS
     1918            char       *pszUserUPN = NULL;
     1919            if (pSessionThread->StartupInfo.szDomain[0])
    17931920            {
    1794                 apszArgs[idxArg++] = "--domain";
    1795                 apszArgs[idxArg++] = pSessionThread->StartupInfo.szDomain;
     1921                int cchbUserUPN = RTStrAPrintf(&pszUserUPN, "%s@%s",
     1922                                               pSessionThread->StartupInfo.szUser,
     1923                                               pSessionThread->StartupInfo.szDomain);
     1924                if (cchbUserUPN > 0)
     1925                {
     1926                    pszUser = pszUserUPN;
     1927                    VGSvcVerbose(3, "Using UPN: %s\n", pszUserUPN);
     1928                }
     1929                else
     1930                    rc = VERR_NO_STR_MEMORY;
    17961931            }
    1797         }
    1798 
    1799         /* Add same verbose flags as parent process. */
    1800         char szParmVerbose[32];
    1801         if (g_cVerbosity > 0)
    1802         {
    1803             unsigned cVs = RT_MIN(g_cVerbosity, RT_ELEMENTS(szParmVerbose) - 2);
    1804             szParmVerbose[0] = '-';
    1805             memset(&szParmVerbose[1], 'v', cVs);
    1806             szParmVerbose[1 + cVs] = '\0';
    1807             apszArgs[idxArg++] = szParmVerbose;
    1808         }
    1809 
    1810         /* Add log file handling. Each session will have an own
    1811          * log file, naming based on the parent log file. */
    1812         char szParmLogFile[sizeof(g_szLogFile) + 128];
    1813         if (g_szLogFile[0])
    1814         {
    1815             const char *pszSuffix = RTPathSuffix(g_szLogFile);
    1816             if (!pszSuffix)
    1817                 pszSuffix = strchr(g_szLogFile, '\0');
    1818             size_t cchBase = pszSuffix - g_szLogFile;
    1819 #ifndef DEBUG
    1820             RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%s%s",
    1821                         cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, pSessionStartupInfo->szUser, pszSuffix);
    1822 #else
    1823             RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), "%.*s-%RU32-%RU32-%s%s",
    1824                         cchBase, g_szLogFile, pSessionStartupInfo->uSessionID, uCtrlSessionThread,
    1825                         pSessionStartupInfo->szUser, pszSuffix);
    1826 #endif
    1827             apszArgs[idxArg++] = "--logfile";
    1828             apszArgs[idxArg++] = szParmLogFile;
    1829         }
    1830 
    1831 #ifdef DEBUG
    1832         VGSvcVerbose(4, "Argv building rc=%Rrc, session flags=%x\n", rc, g_Session.fFlags);
    1833         if (RT_SUCCESS(rc))
    1834         {
    1835             if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDOUT)
    1836                 apszArgs[idxArg++] = "--dump-stdout";
    1837             if (g_Session.fFlags & VBOXSERVICECTRLSESSION_FLAG_DUMPSTDERR)
    1838                 apszArgs[idxArg++] = "--dump-stderr";
    1839         }
    1840 #endif
    1841         apszArgs[idxArg] = NULL;
    1842         Assert(idxArg < RT_ELEMENTS(apszArgs));
    1843 
    1844         if (g_cVerbosity > 3)
    1845         {
    1846             VGSvcVerbose(4, "Spawning parameters:\n");
    1847             for (idxArg = 0; apszArgs[idxArg]; idxArg++)
    1848                 VGSvcVerbose(4, "\t%s\n", apszArgs[idxArg]);
    1849         }
    1850 
    1851         /*
    1852          * Configure standard handles and finally create the process.
    1853          */
    1854         uint32_t fProcCreate = RTPROC_FLAGS_PROFILE;
    1855 #ifdef RT_OS_WINDOWS /* Windows only flags: */
    1856         fProcCreate         |= RTPROC_FLAGS_SERVICE
    1857                             |  RTPROC_FLAGS_HIDDEN;       /** @todo More flags from startup info? */
    1858 #endif
    1859 
    1860 #if 0 /* Pipe handling not needed (yet). */
    1861         /* Setup pipes. */
    1862         rc = GstcntlProcessSetupPipe("|", 0 /*STDIN_FILENO*/,
    1863                                      &pSession->StdIn.hChild, &pSession->StdIn.phChild, &pSession->hStdInW);
    1864         if (RT_SUCCESS(rc))
    1865         {
    1866             rc = GstcntlProcessSetupPipe("|", 1 /*STDOUT_FILENO*/,
    1867                                          &pSession->StdOut.hChild, &pSession->StdOut.phChild, &pSession->hStdOutR);
    18681932            if (RT_SUCCESS(rc))
     1933#endif
    18691934            {
    1870                 rc = GstcntlProcessSetupPipe("|", 2 /*STDERR_FILENO*/,
    1871                                              &pSession->StdErr.hChild, &pSession->StdErr.phChild, &pSession->hStdErrR);
    1872                 if (RT_SUCCESS(rc))
    1873                 {
    1874                     rc = RTPollSetCreate(&pSession->hPollSet);
    1875                     if (RT_SUCCESS(rc))
    1876                         rc = RTPollSetAddPipe(pSession->hPollSet, pSession->hStdInW, RTPOLL_EVT_ERROR,
    1877                                               VBOXSERVICECTRLPIPEID_STDIN);
    1878                     if (RT_SUCCESS(rc))
    1879                         rc = RTPollSetAddPipe(pSession->hPollSet, pSession->hStdOutR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR,
    1880                                               VBOXSERVICECTRLPIPEID_STDOUT);
    1881                     if (RT_SUCCESS(rc))
    1882                         rc = RTPollSetAddPipe(pSession->hPollSet, pSession->hStdErrR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR,
    1883                                               VBOXSERVICECTRLPIPEID_STDERR);
    1884                 }
    1885 
    1886                 if (RT_SUCCESS(rc))
    1887                     rc = RTProcCreateEx(pszExeName, apszArgs, hEnv, fProcCreate,
    1888                                         pSession->StdIn.phChild, pSession->StdOut.phChild, pSession->StdErr.phChild,
    1889                                         !fAnonymous ? pSession->StartupInfo.szUser : NULL,
    1890                                         !fAnonymous ? pSession->StartupInfo.szPassword : NULL,
    1891                                         &pSession->hProcess);
    1892 
    1893                 if (RT_SUCCESS(rc))
    1894                 {
    1895                     /*
    1896                      * Close the child ends of any pipes and redirected files.
    1897                      */
    1898                     int rc2 = RTHandleClose(pSession->StdIn.phChild); AssertRC(rc2);
    1899                     pSession->StdIn.phChild     = NULL;
    1900                     rc2 = RTHandleClose(pSession->StdOut.phChild);    AssertRC(rc2);
    1901                     pSession->StdOut.phChild    = NULL;
    1902                     rc2 = RTHandleClose(pSession->StdErr.phChild);    AssertRC(rc2);
    1903                     pSession->StdErr.phChild    = NULL;
    1904                 }
     1935                /*
     1936                 * Finally, create the process.
     1937                 */
     1938                rc = RTProcCreateEx(pszExeName, apszArgs, RTENV_DEFAULT, fProcCreate,
     1939                                    &hStdIn, &hStdOutAndErr, &hStdOutAndErr,
     1940                                    !fAnonymous ? pszUser : NULL,
     1941                                    !fAnonymous ? pSessionThread->StartupInfo.szPassword : NULL,
     1942                                    &pSessionThread->hProcess);
    19051943            }
    1906         }
    1907 #else
    1908         if (RT_SUCCESS(rc))
    1909         {
    1910             RTHANDLE hStdIn;
    1911             rc = RTFileOpenBitBucket(&hStdIn.u.hFile, RTFILE_O_READ);
    1912             if (RT_SUCCESS(rc))
    1913             {
    1914                 hStdIn.enmType = RTHANDLETYPE_FILE;
    1915 
    1916                 RTHANDLE hStdOutAndErr;
    1917                 rc = RTFileOpenBitBucket(&hStdOutAndErr.u.hFile, RTFILE_O_WRITE);
    1918                 if (RT_SUCCESS(rc))
    1919                 {
    1920                     hStdOutAndErr.enmType = RTHANDLETYPE_FILE;
    1921 
    1922                     const char *pszUser = pSessionThread->StartupInfo.szUser;
    1923 # ifdef RT_OS_WINDOWS
    1924                     /* If a domain name is given, construct an UPN (User Principle Name) with
    1925                      * the domain name built-in, e.g. "[email protected]". */
    1926                     char *pszUserUPN = NULL;
    1927                     if (strlen(pSessionThread->StartupInfo.szDomain))
    1928                     {
    1929                         int cbUserUPN = RTStrAPrintf(&pszUserUPN, "%s@%s",
    1930                                                      pSessionThread->StartupInfo.szUser,
    1931                                                      pSessionThread->StartupInfo.szDomain);
    1932                         if (cbUserUPN > 0)
    1933                         {
    1934                             pszUser = pszUserUPN;
    1935                             VGSvcVerbose(3, "Using UPN: %s\n", pszUserUPN);
    1936                         }
    1937                     }
    1938 # endif
    1939 
    1940                     rc = RTProcCreateEx(pszExeName, apszArgs, RTENV_DEFAULT, fProcCreate,
    1941                                         &hStdIn, &hStdOutAndErr, &hStdOutAndErr,
    1942                                         !fAnonymous ? pszUser : NULL,
    1943                                         !fAnonymous ? pSessionThread->StartupInfo.szPassword : NULL,
    1944                                         &pSessionThread->hProcess);
    1945 # ifdef RT_OS_WINDOWS
    1946                     if (pszUserUPN)
    1947                         RTStrFree(pszUserUPN);
    1948 # endif
    1949                     RTFileClose(hStdOutAndErr.u.hFile);
    1950                 }
    1951 
    1952                 RTFileClose(hStdIn.u.hFile);
    1953             }
    1954         }
    1955 #endif
    1956     }
    1957     else
    1958         rc = VERR_FILE_NOT_FOUND;
     1944#ifdef RT_OS_WINDOWS
     1945            RTStrFree(pszUserUPN);
     1946#endif
     1947            RTFileClose(hStdOutAndErr.u.hFile);
     1948        }
     1949
     1950        RTPipeClose(hStdIn.u.hPipe);
     1951    }
    19591952    return rc;
    19601953}
     
    19921985    }
    19931986#endif
    1994     int rc = VINF_SUCCESS;
    19951987
    19961988    /* Static counter to help tracking session thread <-> process relations. */
    19971989    static uint32_t s_uCtrlSessionThread = 0;
     1990#if 1
     1991    if (++s_uCtrlSessionThread == 100000)
     1992#else /* This must be some joke, right? ;-) */
    19981993    if (s_uCtrlSessionThread++ == UINT32_MAX)
     1994#endif
    19991995        s_uCtrlSessionThread = 0; /* Wrap around to not let IPRT freak out. */
    20001996
     
    20021998     * Allocate and initialize the session thread structure.
    20031999     */
     2000    int rc;
    20042001    PVBOXSERVICECTRLSESSIONTHREAD pSessionThread = (PVBOXSERVICECTRLSESSIONTHREAD)RTMemAllocZ(sizeof(*pSessionThread));
    20052002    if (pSessionThread)
    20062003    {
     2004        //pSessionThread->fShutdown = false;
     2005        //pSessionThread->fStarted  = false;
     2006        //pSessionThread->fStopped  = false;
     2007        pSessionThread->hKeyPipe  = NIL_RTPIPE;
     2008        pSessionThread->Thread    = NIL_RTTHREAD;
     2009        pSessionThread->hProcess  = NIL_RTPROCESS;
     2010
    20072011        /* Copy over session startup info. */
    20082012        memcpy(&pSessionThread->StartupInfo, pSessionStartupInfo, sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO));
    20092013
    2010         pSessionThread->fShutdown = false;
    2011         pSessionThread->fStarted  = false;
    2012         pSessionThread->fStopped  = false;
     2014        /* Generate the secret key. */
     2015        RTRandBytes(pSessionThread->abKey, sizeof(pSessionThread->abKey));
    20132016
    20142017        rc = RTCritSectInit(&pSessionThread->CritSect);
     
    20172020        {
    20182021            /*
    2019              * Start the session thread.
     2022             * Give the session key to the host so it can validate the client.
    20202023             */
    2021             rc = vgsvcVGSvcGstCtrlSessionThreadCreateProcess(pSessionStartupInfo, pSessionThread, s_uCtrlSessionThread);
     2024            if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient))
     2025            {
     2026                for (uint32_t i = 0; i < 10; i++)
     2027                {
     2028                    rc = VbglR3GuestCtrlSessionPrepare(g_idControlSvcClient, pSessionStartupInfo->uSessionID,
     2029                                                       pSessionThread->abKey, sizeof(pSessionThread->abKey));
     2030                    if (rc != VERR_OUT_OF_RESOURCES)
     2031                        break;
     2032                    RTThreadSleep(100);
     2033                }
     2034            }
    20222035            if (RT_SUCCESS(rc))
    20232036            {
    20242037                /*
    2025                  * Start the session thread.
     2038                 * Start the session child process.
    20262039                 */
    2027                 rc = RTThreadCreateF(&pSessionThread->Thread, vgsvcGstCtrlSessionThread,
    2028                                      pSessionThread /*pvUser*/, 0 /*cbStack*/,
    2029                                      RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "sess%u", s_uCtrlSessionThread);
     2040                rc = vgsvcVGSvcGstCtrlSessionThreadCreateProcess(pSessionStartupInfo, pSessionThread, s_uCtrlSessionThread);
    20302041                if (RT_SUCCESS(rc))
    20312042                {
    2032                     /* Wait for the thread to initialize. */
    2033                     rc = RTThreadUserWait(pSessionThread->Thread, RT_MS_1MIN);
    2034                     if (   RT_SUCCESS(rc)
    2035                         && !ASMAtomicReadBool(&pSessionThread->fShutdown))
     2043                    /*
     2044                     * Start the session thread.
     2045                     */
     2046                    rc = RTThreadCreateF(&pSessionThread->Thread, vgsvcGstCtrlSessionThread, pSessionThread /*pvUser*/, 0 /*cbStack*/,
     2047                                         RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "CtrlSess%u", s_uCtrlSessionThread);
     2048                    if (RT_SUCCESS(rc))
    20362049                    {
    2037                         VGSvcVerbose(2, "Thread for session ID=%RU32 started\n", pSessionThread->StartupInfo.uSessionID);
    2038 
    2039                         ASMAtomicXchgBool(&pSessionThread->fStarted, true);
    2040 
    2041                         /* Add session to list. */
    2042                         RTListAppend(pList, &pSessionThread->Node);
    2043                         if (ppSessionThread) /* Return session if wanted. */
    2044                             *ppSessionThread = pSessionThread;
    2045                         return VINF_SUCCESS;
     2050                        /* Wait for the thread to initialize. */
     2051                        rc = RTThreadUserWait(pSessionThread->Thread, RT_MS_1MIN);
     2052                        if (   RT_SUCCESS(rc)
     2053                            && !ASMAtomicReadBool(&pSessionThread->fShutdown))
     2054                        {
     2055                            VGSvcVerbose(2, "Thread for session ID=%RU32 started\n", pSessionThread->StartupInfo.uSessionID);
     2056
     2057                            ASMAtomicXchgBool(&pSessionThread->fStarted, true);
     2058
     2059                            /* Add session to list. */
     2060                            RTListAppend(pList, &pSessionThread->Node);
     2061                            if (ppSessionThread) /* Return session if wanted. */
     2062                                *ppSessionThread = pSessionThread;
     2063                            return VINF_SUCCESS;
     2064                        }
     2065
     2066                        /*
     2067                         * Bail out.
     2068                         */
     2069                        VGSvcError("Thread for session ID=%RU32 failed to start, rc=%Rrc\n",
     2070                                   pSessionThread->StartupInfo.uSessionID, rc);
     2071                        if (RT_SUCCESS_NP(rc))
     2072                            rc = VERR_CANT_CREATE; /** @todo Find a better rc. */
    20462073                    }
    2047 
    2048                     /*
    2049                      * Bail out.
    2050                      */
    2051                     VGSvcError("Thread for session ID=%RU32 failed to start, rc=%Rrc\n",
    2052                                pSessionThread->StartupInfo.uSessionID, rc);
    2053                     if (RT_SUCCESS_NP(rc))
    2054                         rc = VERR_CANT_CREATE; /** @todo Find a better rc. */
     2074                    else
     2075                        VGSvcError("Creating session thread failed, rc=%Rrc\n", rc);
     2076
     2077                    RTProcTerminate(pSessionThread->hProcess);
     2078                    uint32_t cMsWait = 1;
     2079                    while (   RTProcWait(pSessionThread->hProcess, RTPROCWAIT_FLAGS_NOBLOCK, NULL) == VERR_PROCESS_RUNNING
     2080                           && cMsWait <= 9) /* 1023 ms */
     2081                    {
     2082                        RTThreadSleep(cMsWait);
     2083                        cMsWait <<= 1;
     2084                    }
    20552085                }
    2056                 else
    2057                     VGSvcError("Creating session thread failed, rc=%Rrc\n", rc);
    2058 
    2059                 RTProcTerminate(pSessionThread->hProcess);
    2060                 uint32_t cMsWait = 1;
    2061                 while (   RTProcWait(pSessionThread->hProcess, RTPROCWAIT_FLAGS_NOBLOCK, NULL) == VERR_PROCESS_RUNNING
    2062                        && cMsWait <= 9) /* 1023 ms */
    2063                 {
    2064                     RTThreadSleep(cMsWait);
    2065                     cMsWait <<= 1;
    2066                 }
     2086
     2087                if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient))
     2088                    VbglR3GuestCtrlSessionCancelPrepared(g_idControlSvcClient, pSessionStartupInfo->uSessionID);
    20672089            }
     2090            else
     2091                VGSvcVerbose(3, "VbglR3GuestCtrlSessionPrepare failed: %Rrc\n", rc);
     2092            RTPipeClose(pSessionThread->hKeyPipe);
     2093            pSessionThread->hKeyPipe = NIL_RTPIPE;
    20682094            RTCritSectDelete(&pSessionThread->CritSect);
    20692095        }
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