VirtualBox

Changeset 44935 in vbox for trunk/src/VBox/Additions/common


Ignore:
Timestamp:
Mar 6, 2013 4:40:36 PM (12 years ago)
Author:
vboxsync
Message:

GuestCtrl: More code for guest session infrastructure handling (untested, work in progress). Added IGuestSession.status for (later) asynchronous handling.

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r44869 r44935  
    193193    if (RT_SUCCESS(rc))
    194194    {
    195         VBoxServiceVerbose(3, "Service client ID: %#x\n", g_uControlSvcClientID);
     195        VBoxServiceVerbose(3, "Guest control service client ID=%RU32\n",
     196                           g_uControlSvcClientID);
    196197
    197198        /* Init lists. */
     
    836837         * wants to use. Store it in the host context for later calls. */
    837838        pHostCtx->uProtocol = ssInfo.uProtocol;
     839        VBoxServiceVerbose(3, "Client ID=%RU32 now is using protocol %RU32\n",
     840                           pHostCtx->uClientID, pHostCtx->uProtocol);
    838841
    839842        rc = GstCntlSessionOpen(&ssInfo, NULL /* Node */);
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h

    r44869 r44935  
    255255    /** Domain of the user account. */
    256256    char                            szDomain[GUESTPROCESS_MAX_DOMAIN_LEN];
    257     /** Session creation flags. */
     257    /** Session creation flags.
     258     *  @sa VBOXSERVICECTRLSESSIONSTARTUPFLAG_* flags. */
    258259    uint32_t                        uFlags;
    259260} VBOXSERVICECTRLSESSIONSTARTUPINFO;
     
    262263
    263264/**
    264  * Structure for one (opened) guest session.
     265 * Structure for a (forked) guest session.
    265266 */
    266267typedef struct VBOXSERVICECTRLSESSION
     
    278279    /** Process handle for forked child. */
    279280    RTPROCESS                       hProcess;
     281    /** Shutdown indicator; will be set when the thread
     282      * needs (or is asked) to shutdown. */
     283    bool volatile                   fShutdown;
     284    /** Indicator set by the service thread exiting. */
     285    bool volatile                   fStopped;
     286    /** Whether the thread was started or not. */
     287    bool                            fStarted;
     288#if 0 /* Pipe IPC not used yet. */
    280289    /** Pollset containing all the pipes. */
    281290    RTPOLLSET                       hPollSet;
     
    295304    /** The other end of hNotificationPipeW. */
    296305    RTPIPE                          hNotificationPipeR;
     306#endif
    297307} VBOXSERVICECTRLSESSION;
    298308/** Pointer to thread data. */
     
    314324extern int                      GstCntlSessionOpen(const PVBOXSERVICECTRLSESSIONSTARTUPINFO pSessionStartupInfo, PRTLISTNODE pNode);
    315325extern int                      GstCntlSessionClose(PVBOXSERVICECTRLSESSION pSession, uint32_t uFlags);
     326extern int                      GstCntlSessionTerminate(PVBOXSERVICECTRLSESSION pSession);
    316327extern RTEXITCODE               VBoxServiceControlSessionForkInit(int argc, char **argv);
    317328
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r44926 r44935  
    2121*   Header Files                                                               *
    2222*******************************************************************************/
     23#include <iprt/asm.h>
    2324#include <iprt/assert.h>
    2425#include <iprt/env.h>
     
    5657static int                  gstcntlSessionHandleFileSeek(uint32_t uClientId, uint32_t cParms);
    5758static int                  gstcntlSessionHandleFileTell(uint32_t uClientId, uint32_t cParms);
     59static DECLCALLBACK(int)    gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser);
    5860
    5961/** The session ID of the forked session process. */
     
    475477
    476478
     479/**
     480 * Thread main routine for a forked guest session. This
     481 * thread runs in the main executable to control the forked
     482 * session process.
     483 *
     484 * @return IPRT status code.
     485 * @param  RTTHREAD             Pointer to the thread's data.
     486 * @param  void*                User-supplied argument pointer.
     487 *
     488 */
     489static DECLCALLBACK(int) gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser)
     490{
     491    PVBOXSERVICECTRLSESSION pSession = (PVBOXSERVICECTRLSESSION)pvUser;
     492    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     493
     494    VBoxServiceVerbose(3, "Session ID=%RU32 thread running\n",
     495                       pSession->StartupInfo.uSessionID);
     496
     497    int rc = VINF_SUCCESS;
     498
     499    /* Let caller know that we're done initializing. */
     500    int rc2 = RTThreadUserSignal(RTThreadSelf());
     501    if (RT_SUCCESS(rc))
     502        rc = rc2;
     503
     504    if (RT_SUCCESS(rc))
     505    {
     506        RTPROCSTATUS ProcessStatus;
     507        int rc2;
     508        for (;;)
     509        {
     510            rc2 = RTProcWaitNoResume(pSession->hProcess, RTPROCWAIT_FLAGS_BLOCK,
     511                                     &ProcessStatus);
     512            if (RT_UNLIKELY(rc2 == VERR_INTERRUPTED))
     513                continue;
     514            else if (   rc2 == VINF_SUCCESS
     515                     || rc2 == VERR_PROCESS_NOT_FOUND)
     516            {
     517                break;
     518            }
     519            else
     520                AssertMsgBreak(rc2 == VERR_PROCESS_RUNNING,
     521                               ("Got unexpected rc=%Rrc while waiting for session process termination\n", rc2));
     522        }
     523
     524        VBoxServiceVerbose(3, "Guest session process ID=%RU32 terminated with rc=%Rrc, reason=%ld, status=%d\n",
     525                           pSession->StartupInfo.uSessionID, rc,
     526                           ProcessStatus.enmReason, ProcessStatus.iStatus);
     527    }
     528
     529    VBoxServiceVerbose(3, "Session ID=%RU32 thread ended\n", pSession->StartupInfo.uSessionID);
     530    return rc;
     531}
     532
     533
    477534RTEXITCODE gstcntlSessionWorker(void)
    478535{
    479536    bool fSessionFilter = true;
     537
     538    VBoxServiceVerbose(0, "Hi, this is guest session ID=%RU32\n",
     539                       g_uSessionID);
    480540
    481541    uint32_t uClientID;
     
    487547
    488548        rc = VbglR3GuestCtrlMsgSetFilter(uClientID, uFilterAdd, 0 /* Filter remove */);
     549        VBoxServiceVerbose(3, "Setting message filterAdd=%RU32 returned %Rrc\n",
     550                           uFilterAdd, rc);
     551
    489552        if (   RT_FAILURE(rc)
    490553            && rc == VERR_NOT_SUPPORTED)
     
    531594            {
    532595                VBoxServiceVerbose(3, "Msg=%RU32 (%RU32 parms) retrieved\n", uMsg, cParms);
    533             }
    534 
    535             VBoxServiceVerbose(3, "Msg=%RU32 (%RU32 parms) retrieved\n", uMsg, cParms);
    536 
    537             /** @todo Guest session ID change detection? */
    538 
    539             switch (uMsg)
    540             {
    541                 case HOST_CANCEL_PENDING_WAITS:
    542                     /* Fall thru is intentional. */
    543                 case HOST_SESSION_CLOSE:
    544                     /* Shutdown this fork. */
    545                     rc = gstcntlSessionForkShutdown(uClientID, cParms);
    546                     fShutdown = true; /* Shutdown in any case. */
    547                     break;
    548 
    549                 case HOST_FILE_OPEN:
    550                     rc = gstcntlSessionHandleFileOpen(uClientID, cParms);
    551                     break;
    552 
    553                 case HOST_FILE_CLOSE:
    554                     rc = gstcntlSessionHandleFileClose(uClientID, cParms);
    555                     break;
    556 
    557                 case HOST_FILE_READ:
    558                     rc = gstcntlSessionHandleFileRead(uClientID, cParms,
    559                                                       pvScratchBuf, cbScratchBuf);
    560                     break;
    561 
    562                 case HOST_FILE_READ_AT:
    563                     rc = gstcntlSessionHandleFileReadAt(uClientID, cParms,
    564                                                         pvScratchBuf, cbScratchBuf);
    565                     break;
    566 
    567                 case HOST_FILE_WRITE:
    568                     rc = gstcntlSessionHandleFileWrite(uClientID, cParms,
    569                                                        pvScratchBuf, cbScratchBuf);
    570                     break;
    571 
    572                 case HOST_FILE_WRITE_AT:
    573                     rc = gstcntlSessionHandleFileWriteAt(uClientID, cParms,
    574                                                          pvScratchBuf, cbScratchBuf);
    575                     break;
    576 
    577                 case HOST_FILE_SEEK:
    578                     rc = gstcntlSessionHandleFileSeek(uClientID, cParms);
    579                     break;
    580 
    581                 case HOST_FILE_TELL:
    582                     rc = gstcntlSessionHandleFileTell(uClientID, cParms);
    583                     break;
    584 
    585                 default:
    586                     VBoxServiceVerbose(3, "Unsupported message from host, uMsg=%RU32, cParms=%RU32\n",
    587                                        uMsg, cParms);
    588                     /* Don't terminate here; just wait for the next message. */
    589                     break;
     596
     597                /** @todo Guest session ID change detection? */
     598
     599                switch (uMsg)
     600                {
     601                    case HOST_CANCEL_PENDING_WAITS:
     602                        /* Fall thru is intentional. */
     603                    case HOST_SESSION_CLOSE:
     604                        /* Shutdown this fork. */
     605                        rc = gstcntlSessionForkShutdown(uClientID, cParms);
     606                        fShutdown = true; /* Shutdown in any case. */
     607                        break;
     608
     609                    case HOST_FILE_OPEN:
     610                        rc = gstcntlSessionHandleFileOpen(uClientID, cParms);
     611                        break;
     612
     613                    case HOST_FILE_CLOSE:
     614                        rc = gstcntlSessionHandleFileClose(uClientID, cParms);
     615                        break;
     616
     617                    case HOST_FILE_READ:
     618                        rc = gstcntlSessionHandleFileRead(uClientID, cParms,
     619                                                          pvScratchBuf, cbScratchBuf);
     620                        break;
     621
     622                    case HOST_FILE_READ_AT:
     623                        rc = gstcntlSessionHandleFileReadAt(uClientID, cParms,
     624                                                            pvScratchBuf, cbScratchBuf);
     625                        break;
     626
     627                    case HOST_FILE_WRITE:
     628                        rc = gstcntlSessionHandleFileWrite(uClientID, cParms,
     629                                                           pvScratchBuf, cbScratchBuf);
     630                        break;
     631
     632                    case HOST_FILE_WRITE_AT:
     633                        rc = gstcntlSessionHandleFileWriteAt(uClientID, cParms,
     634                                                             pvScratchBuf, cbScratchBuf);
     635                        break;
     636
     637                    case HOST_FILE_SEEK:
     638                        rc = gstcntlSessionHandleFileSeek(uClientID, cParms);
     639                        break;
     640
     641                    case HOST_FILE_TELL:
     642                        rc = gstcntlSessionHandleFileTell(uClientID, cParms);
     643                        break;
     644
     645                    default:
     646                        VBoxServiceVerbose(3, "Unsupported message from host, uMsg=%RU32, cParms=%RU32\n",
     647                                           uMsg, cParms);
     648                        /* Don't terminate here; just wait for the next message. */
     649                        break;
     650                }
    590651            }
    591652
    592653            if (fShutdown)
    593654                break;
     655
     656            /* Let's sleep for a bit and let others run ... */
     657            RTThreadYield();
    594658        }
    595659    }
     
    610674/**
    611675 * Creates a guest session. This will spawn a new VBoxService.exe instance under
    612  * behalf of the given user which then will act as a session host.
     676 * behalf of the given user which then will act as a session host. On successful
     677 * open, the session will be added to the session list.
    613678 *
    614679 * @return  IPRT status code.
     
    645710        memcpy(&pSession->StartupInfo, pSessionStartupInfo, sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO));
    646711
    647         VBoxServiceVerbose(3, "Forking new guest session szUser=%s, szPassword=%s, szDomain=%s, uFlags=%x, using protocol %RU32\n",
    648                            pSessionStartupInfo->szUser,
     712        pSession->fShutdown = false;
     713        pSession->fStarted  = false;
     714        pSession->fStopped  = false;
     715
     716        /* Is this an anonymous session? */
     717        /* Anonymous sessions run with the same privileges as the main VBoxService executable. */
     718        bool fAnonymous = !RT_BOOL(strlen(pSession->StartupInfo.szUser));
     719        if (fAnonymous)
     720        {
     721            Assert(!strlen(pSession->StartupInfo.szPassword));
     722            Assert(!strlen(pSession->StartupInfo.szDomain));
     723
     724            VBoxServiceVerbose(3, "New anonymous guest session ID=%RU32 created, uFlags=%x, using protocol %RU32\n",
     725                               pSessionStartupInfo->uSessionID,
     726                               pSessionStartupInfo->uFlags,
     727                               pSessionStartupInfo->uProtocol);
     728        }
     729        else
     730        {
     731            VBoxServiceVerbose(3, "Forking new guest session ID=%RU32, szUser=%s, szPassword=%s, szDomain=%s, uFlags=%x, using protocol %RU32\n",
     732                               pSessionStartupInfo->uSessionID,
     733                               pSessionStartupInfo->szUser,
    649734#ifdef DEBUG
    650                            pSessionStartupInfo->szPassword,
     735                               pSessionStartupInfo->szPassword,
    651736#else
    652                            "XXX", /* Never show passwords in release mode. */
     737                               "XXX", /* Never show passwords in release mode. */
    653738#endif
    654                            pSessionStartupInfo->szDomain,
    655                            pSessionStartupInfo->uFlags,
    656                            pSessionStartupInfo->uProtocol);
     739                               pSessionStartupInfo->szDomain,
     740                               pSessionStartupInfo->uFlags,
     741                               pSessionStartupInfo->uProtocol);
     742        }
    657743
    658744        rc = RTCritSectInit(&pSession->CritSect);
     
    665751        {
    666752            char szParmUserName[GUESTPROCESS_MAX_USER_LEN + 32];
    667             if (!RTStrPrintf(szParmUserName, sizeof(szParmUserName), "--username=%s", pSession->StartupInfo.szUser))
    668                 rc = VERR_BUFFER_OVERFLOW;
     753            if (!fAnonymous)
     754            {
     755                if (!RTStrPrintf(szParmUserName, sizeof(szParmUserName), "--username=%s", pSession->StartupInfo.szUser))
     756                    rc = VERR_BUFFER_OVERFLOW;
     757            }
    669758            char szParmSessionID[32];
    670759            if (RT_SUCCESS(rc) && !RTStrPrintf(szParmSessionID, sizeof(szParmSessionID), "--session-id=%RU32",
     
    689778                papszArgs[iOptIdx++] = szParmSessionID;
    690779                papszArgs[iOptIdx++] = szParmSessionProto;
    691                 papszArgs[iOptIdx++] = szParmUserName;
     780                if (!fAnonymous)
     781                    papszArgs[iOptIdx++] = szParmUserName;
    692782
    693783                /* Add same verbose flags as parent process. */
     
    733823                            {
    734824                                if (!RTStrPrintf(szParmLogFile, sizeof(szParmLogFile),
    735                                                  "--logfile %s", pszLogFile))
     825                                                 "--logfile=%s", pszLogFile))
    736826                                {
    737827                                    rc2 = VERR_BUFFER_OVERFLOW;
     
    798888                            rc = RTProcCreateEx(pszExeName, papszArgs, RTENV_DEFAULT, uProcFlags,
    799889                                                pSession->StdIn.phChild, pSession->StdOut.phChild, pSession->StdErr.phChild,
    800                                                 pSession->StartupInfo.szUser,
    801                                                 pSession->StartupInfo.szPassword,
     890                                                !fAnonymous ? pSession->StartupInfo.szUser : NULL,
     891                                                !fAnonymous ? pSession->StartupInfo.szPassword : NULL,
    802892                                                &pSession->hProcess);
    803893                        }
     
    818908                }
    819909#else
    820                 /** @todo Do we need a custom environment block? */
    821                 rc = RTProcCreateEx(pszExeName, papszArgs, RTENV_DEFAULT, uProcFlags,
    822                                     NULL /* StdIn */, NULL /* StdOut */, NULL /* StdErr */,
    823                                     pSession->StartupInfo.szUser,
    824                                     pSession->StartupInfo.szPassword,
    825                                     &pSession->hProcess);
     910                RTHANDLE hStdIn;
     911                rc = RTFileOpenBitBucket(&hStdIn.u.hFile, RTFILE_O_READ);
     912                if (RT_SUCCESS(rc))
     913                {
     914                    hStdIn.enmType = RTHANDLETYPE_FILE;
     915
     916                    RTHANDLE hStdOutAndErr;
     917                    rc = RTFileOpenBitBucket(&hStdOutAndErr.u.hFile, RTFILE_O_WRITE);
     918                    if (RT_SUCCESS(rc))
     919                    {
     920                        hStdOutAndErr.enmType = RTHANDLETYPE_FILE;
     921
     922                        /** @todo Do we need a custom/cloned environment block? */
     923                        rc = RTProcCreateEx(pszExeName, papszArgs, RTENV_DEFAULT, uProcFlags,
     924                                            &hStdIn, &hStdOutAndErr, &hStdOutAndErr,
     925                                            !fAnonymous ? pSession->StartupInfo.szUser : NULL,
     926                                            !fAnonymous ? pSession->StartupInfo.szPassword : NULL,
     927                                            &pSession->hProcess);
     928
     929                        RTFileClose(hStdOutAndErr.u.hFile);
     930                    }
     931
     932                    RTFileClose(hStdOutAndErr.u.hFile);
     933                }
    826934#endif
    827935            }
     
    832940        if (RT_SUCCESS(rc))
    833941        {
    834             /* Add session to list. */
    835             /* rc = */ RTListAppend(&g_lstControlSessions, &pSession->Node);
    836             if (pNode) /* Return node if wanted. */
    837                 pNode = &pSession->Node;
    838         }
    839         else
     942            /* Start session thread. */
     943            static uint32_t s_uCtrlSessionThread = 0;
     944            if (s_uCtrlSessionThread++ == UINT32_MAX)
     945                s_uCtrlSessionThread = 0; /* Wrap around to not let IPRT freak out. */
     946            rc = RTThreadCreateF(&pSession->Thread, gstcntlSessionThread,
     947                                 pSession /*pvUser*/, 0 /*cbStack*/,
     948                                 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "sess%u", s_uCtrlSessionThread);
     949            if (RT_FAILURE(rc))
     950            {
     951                VBoxServiceError("Creating session thread failed, rc=%Rrc\n", rc);
     952            }
     953            else
     954            {
     955                /* Wait for the thread to initialize. */
     956                rc = RTThreadUserWait(pSession->Thread, 60 * 1000 /* 60 seconds max. */);
     957                AssertRC(rc);
     958                if (   ASMAtomicReadBool(&pSession->fShutdown)
     959                    || RT_FAILURE(rc))
     960                {
     961                    VBoxServiceError("Thread for session ID=%RU32 failed to start\n",
     962                                     pSession->StartupInfo.uSessionID);
     963                    rc = VERR_CANT_CREATE; /** @todo Find a better rc. */
     964                }
     965                else
     966                {
     967                    ASMAtomicXchgBool(&pSession->fStarted, true);
     968
     969                    /* Add session to list. */
     970                    /* rc = */ RTListAppend(&g_lstControlSessions, &pSession->Node);
     971                    if (pNode) /* Return node if wanted. */
     972                        pNode = &pSession->Node;
     973                }
     974            }
     975        }
     976
     977        if (RT_FAILURE(rc))
    840978        {
    841979            RTMemFree(pSession);
     
    851989
    852990/**
    853  * Closes a formerly opened guest session.
     991 * Closes a formerly opened guest session and removes it from
     992 * the session list.
    854993 *
    855994 * @return  IPRT status code.
    856995 * @param   pSession                Guest session to close.
    857  * @param   uFlags                  Termination flags.
     996 * @param   uFlags                  Closing flags.
    858997 */
    859998int GstCntlSessionClose(PVBOXSERVICECTRLSESSION pSession, uint32_t uFlags)
     
    8611000    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    8621001
    863     /** @todo Implement session termination. */
    864     return VERR_NOT_IMPLEMENTED;
     1002    int rc = VINF_SUCCESS;
     1003
     1004    /* The fork should have received the same closing request,
     1005     * so just wait 30s for the process to close. On timeout kill
     1006     * it in a not so gentle manner. */
     1007    if (   pSession->Thread != NIL_RTTHREAD
     1008        && ASMAtomicReadBool(&pSession->fStarted))
     1009    {
     1010        bool fAlive = true;
     1011        uint64_t u64Start = RTTimeMilliTS();
     1012        uint32_t cMsTimeout = 30 * 1000; /* 30 seconds. */
     1013
     1014        VBoxServiceVerbose(3, "Waiting for session ID=%RU32 to close (%RU32ms) ...\n",
     1015                           pSession->StartupInfo.uSessionID, cMsTimeout);
     1016
     1017        int rcThread;
     1018        rc = RTThreadWait(pSession->Thread, cMsTimeout, &rcThread);
     1019        if (RT_FAILURE(rc))
     1020        {
     1021            VBoxServiceError("Waiting for session ID=%RU32 to close failed with rc=%Rrc\n", rc);
     1022        }
     1023        else
     1024        {
     1025            fAlive = false;
     1026            VBoxServiceVerbose(3, "Session ID=%RU32 thread ended with rc=%Rrc\n",
     1027                               pSession->StartupInfo.uSessionID, rcThread);
     1028        }
     1029#if 0
     1030        for (;;)
     1031        {
     1032            uint64_t u64Now = RTTimeMilliTS();
     1033            uint64_t cMsElapsed = u64Now - u64Start;
     1034
     1035            if (cMsElapsed >= cMsTimeout)
     1036                break;
     1037
     1038            RTPROCSTATUS ProcessStatus;
     1039            int rc2 = RTProcWaitNoResume(pSession->hProcess, RTPROCWAIT_FLAGS_NOBLOCK,
     1040                                         &ProcessStatus);
     1041            if (RT_UNLIKELY(rc2 == VERR_INTERRUPTED))
     1042                continue;
     1043            else if (   rc2 == VINF_SUCCESS
     1044                     || rc2 == VERR_PROCESS_NOT_FOUND)
     1045            {
     1046                fAlive = false;
     1047                break;
     1048            }
     1049            else
     1050                AssertMsgBreak(rc2 == VERR_PROCESS_RUNNING,
     1051                               ("Got unexpected rc=%Rrc while waiting for session process termination\n", rc2));
     1052
     1053            RTThreadSleep(100); /* Wait a bit. */
     1054        }
     1055    #endif
     1056
     1057        if (fAlive)
     1058        {
     1059            VBoxServiceVerbose(3, "Session ID=%RU32 still alive, killing ...\n",
     1060                               pSession->StartupInfo.uSessionID);
     1061            int rc2 = GstCntlSessionTerminate(pSession);
     1062            if (RT_SUCCESS(rc))
     1063                rc = rc2;
     1064        }
     1065        else
     1066            VBoxServiceVerbose(3, "Session ID=%RU32 has been closed\n",
     1067                               pSession->StartupInfo.uSessionID);
     1068
     1069        /* Remove session from list and destroy object. */
     1070        RTListNodeRemove(&pSession->Node);
     1071
     1072        RTMemFree(pSession);
     1073        pSession = NULL;
     1074    }
     1075
     1076    return rc;
    8651077}
    8661078
     
    8701082 *
    8711083 * @return  IPRT status code.
    872  * @param   uFlags                  Termination flags.
     1084 * @param   uFlags                  Closing flags.
    8731085 */
    8741086int GstCntlSessionCloseAll(uint32_t uFlags)
     
    8761088    int rc = VINF_SUCCESS;
    8771089
    878     VBoxServiceVerbose(3, "GstCntlSessionCloseAll\n");
    879 
    8801090    PVBOXSERVICECTRLSESSION pSessionCur;
    8811091    RTListForEach(&g_lstControlSessions, pSessionCur, VBOXSERVICECTRLSESSION, Node)
     
    8871097            /* Keep going. */
    8881098        }
     1099    }
     1100
     1101    return rc;
     1102}
     1103
     1104
     1105/**
     1106 * Terminates a formerly opened guest session. Only
     1107 * use this as a last action!
     1108 *
     1109 * @return  IPRT status code.
     1110 * @param   pSession                Guest session to terminate.
     1111 */
     1112int GstCntlSessionTerminate(PVBOXSERVICECTRLSESSION pSession)
     1113{
     1114    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     1115
     1116    int rc;
     1117
     1118    for (int i = 0; i < 3; i++)
     1119    {
     1120        rc = RTProcTerminate(pSession->hProcess);
     1121        if (RT_SUCCESS(rc))
     1122            break;
     1123        RTThreadSleep(1000);
    8891124    }
    8901125
     
    9721207static int gstcntlSessionForkShutdown(uint32_t uClientId, uint32_t cParms)
    9731208{
    974     VBoxServiceVerbose(0, "Session %RU32 is going to shutdown ...\n", g_uSessionID);
     1209    VBoxServiceVerbose(0, "Session %RU32 is about to shutdown ...\n", g_uSessionID);
    9751210
    9761211    /* Close all left guest files. */
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