VirtualBox

Changeset 89108 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
May 17, 2021 3:37:57 PM (4 years ago)
Author:
vboxsync
Message:

FE/VBoxHeadless: On Windows also listen to console control events
(Ctrl-C, Ctrl-Break, Close) and terminate the VM. By default try to
save state of the VM when we need to terminate it, don't just yank the
virtual power cord. bugref:8161.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp

    r89095 r89108  
    863863    {
    864864        case WM_QUERYENDSESSION:
    865             if (lParam != 0)
    866                 LogRel(("VBoxHeadless: WM_QUERYENDSESSION (0x%08lx)\n", (unsigned long)lParam));
    867             else
    868                 LogRel(("VBoxHeadless: WM_QUERYENDSESSION\n"));
     865            LogRel(("VBoxHeadless: WM_QUERYENDSESSION:%s%s%s%s (0x%08lx)\n",
     866                    lParam == 0                  ? " shutdown" : "",
     867                    lParam & ENDSESSION_CRITICAL ? " critical" : "",
     868                    lParam & ENDSESSION_LOGOFF   ? " logoff"   : "",
     869                    lParam & ENDSESSION_CLOSEAPP ? " close"    : "",
     870                    (unsigned long)lParam));
    869871
    870872            /* tell the user what we are doing */
     
    902904    }
    903905    return lResult;
     906}
     907
     908
     909static const char * const ctrl_event_names[] = {
     910    "CTRL_C_EVENT",
     911    "CTRL_BREAK_EVENT",
     912    "CTRL_CLOSE_EVENT",
     913    /* reserved, not used */
     914    "<console control event 3>",
     915    "<console control event 4>",
     916    /* not sent to processes that load gdi32.dll or user32.dll */
     917    "CTRL_LOGOFF_EVENT",
     918    "CTRL_SHUTDOWN_EVENT",
     919};
     920
     921
     922BOOL WINAPI
     923ConsoleCtrlHandler(DWORD dwCtrlType) RT_NOTHROW_DEF
     924{
     925    const char *signame;
     926    char namebuf[48];
     927    int rc;
     928
     929    if (dwCtrlType < RT_ELEMENTS(ctrl_event_names))
     930        signame = ctrl_event_names[dwCtrlType];
     931    else
     932    {
     933        /* should not happen, but be prepared */
     934        RTStrPrintf(namebuf, sizeof(namebuf),
     935                    "<console control event %lu>", (unsigned long)dwCtrlType);
     936        signame = namebuf;
     937    }
     938    LogRel(("VBoxHeadless: got %s\n", signame));
     939    RTMsgInfo("Got %s\n", signame);
     940    RTMsgInfo("");
     941
     942    /* tell the VM to save state/power off */
     943    g_fTerminateFE = true;
     944    gEventQ->interruptEventQueueProcessing();
     945
     946    /*
     947     * We don't need to wait for Ctrl-C / Ctrl-Break, but we must wait
     948     * for Close, or we will be killed before the VM is saved.
     949     */
     950    if (g_hCanQuit != NIL_RTSEMEVENT)
     951    {
     952        LogRel(("VBoxHeadless: waiting for VM termination...\n"));
     953
     954        rc = RTSemEventWait(g_hCanQuit, RT_INDEFINITE_WAIT);
     955        if (RT_FAILURE(rc))
     956            LogRel(("VBoxHeadless: Failed to wait for VM termination: %Rrc\n", rc));
     957    }
     958
     959    /* tell the system we handled it */
     960    LogRel(("VBoxHeadless: ConsoleCtrlHandler: return\n"));
     961    return TRUE;
    904962}
    905963#endif /* RT_OS_WINDOWS */
     
    15761634#ifdef RT_OS_WINDOWS
    15771635        /*
     1636         * Register windows console signal handler to react to Ctrl-C,
     1637         * Ctrl-Break, Close.
     1638         */
     1639        ::SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
     1640
     1641        /*
    15781642         * Spawn windows message pump to monitor session events.
    15791643         */
     
    16651729
    16661730        ComPtr<IProgress> pProgress;
    1667 #ifdef VBOX_WITH_SAVESTATE_ON_SIGNAL
    16681731        if (!machine.isNull())
    16691732            CHECK_ERROR_BREAK(machine, SaveState(pProgress.asOutParam()));
    16701733        else
    1671 #endif
    16721734            CHECK_ERROR_BREAK(gConsole, PowerDown(pProgress.asOutParam()));
    16731735
     
    16751737        if (FAILED(rc))
    16761738        {
    1677             RTPrintf("VBoxHeadless: ERROR: Failed to power down VM!");
    16781739            com::ErrorInfo info;
    16791740            if (!info.isFullAvailable() && !info.isBasicAvailable())
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