Index: /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp	(revision 41359)
+++ /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp	(revision 41360)
@@ -40,5 +40,5 @@
     GETOPTDEF_APIMON_ISLN_RESPONSE,
     GETOPTDEF_APIMON_ISLN_TIMEOUT,
-    GETOPTDEF_APIMON_TRIGGER_TIMEOUT
+    GETOPTDEF_APIMON_RESP_TIMEOUT
 };
 
@@ -50,5 +50,5 @@
     { "--apimon-isln-response",     GETOPTDEF_APIMON_ISLN_RESPONSE,  RTGETOPT_REQ_STRING },
     { "--apimon-isln-timeout",      GETOPTDEF_APIMON_ISLN_TIMEOUT,   RTGETOPT_REQ_UINT32 },
-    { "--apimon-trigger-timeout",   GETOPTDEF_APIMON_ISLN_TIMEOUT,   RTGETOPT_REQ_UINT32 }
+    { "--apimon-resp-timeout",      GETOPTDEF_APIMON_RESP_TIMEOUT,   RTGETOPT_REQ_UINT32 }
 };
 
@@ -57,4 +57,6 @@
     /** Unknown / unhandled response. */
     APIMON_RESPONSE_NONE       = 0,
+    /** Pauses the VM execution. */
+    APIMON_RESPONSE_PAUSE      = 10,
     /** Does a hard power off. */
     APIMON_RESPONSE_POWEROFF   = 200,
@@ -71,5 +73,5 @@
 static unsigned long                g_ulAPIMonIslnTimeoutMS = 0;
 static Bstr                         g_strAPIMonIslnLastBeat;
-static unsigned long                g_ulAPIMonTriggerTimeoutMS = 0;
+static unsigned long                g_ulAPIMonResponseTimeoutMS = 0;
 static uint64_t                     g_uAPIMonIslnLastBeatMS = 0;
 
@@ -80,8 +82,20 @@
 
     int rc = VINF_SUCCESS;
-    if (   !RTStrICmp(pszResponse, "poweroff")
-        || !RTStrICmp(pszResponse, "powerdown"))
+    if (!RTStrICmp(pszResponse, "none"))
+    {
+        *pResp = APIMON_RESPONSE_NONE;
+    }
+    else if (!RTStrICmp(pszResponse, "pause"))
+    {
+        *pResp = APIMON_RESPONSE_PAUSE;
+    }
+    else if (   !RTStrICmp(pszResponse, "poweroff")
+             || !RTStrICmp(pszResponse, "powerdown"))
     {
         *pResp = APIMON_RESPONSE_POWEROFF;
+    }
+    else if (!RTStrICmp(pszResponse, "save"))
+    {
+        *pResp = APIMON_RESPONSE_SAVE;
     }
     else if (   !RTStrICmp(pszResponse, "shutdown")
@@ -90,8 +104,4 @@
         *pResp = APIMON_RESPONSE_SHUTDOWN;
     }
-    else if (!RTStrICmp(pszResponse, "save"))
-    {
-        *pResp = APIMON_RESPONSE_SAVE;
-    }
     else
     {
@@ -105,12 +115,14 @@
 static const char* apimonResponseToStr(APIMON_RESPONSE enmResp)
 {
-    if (APIMON_RESPONSE_POWEROFF == enmResp)
+    if (APIMON_RESPONSE_NONE == enmResp)
+        return "none";
+    else if (APIMON_RESPONSE_PAUSE == enmResp)
+        return "pausing";
+    else if (APIMON_RESPONSE_POWEROFF == enmResp)
         return "powering off";
+    else if (APIMON_RESPONSE_SAVE == enmResp)
+        return "saving state";
     else if (APIMON_RESPONSE_SHUTDOWN == enmResp)
         return "shutting down";
-    else if (APIMON_RESPONSE_SAVE == enmResp)
-        return "saving state";
-    else if (APIMON_RESPONSE_NONE == enmResp)
-        return "none";
 
     return "unknown";
@@ -185,108 +197,117 @@
     CHECK_ERROR_RET(g_pVirtualBox, FindMachine(strUuid.raw(),
                                                machine.asOutParam()), VERR_NOT_FOUND);
-
-    /* Open a session for the VM. */
-    CHECK_ERROR_RET(machine, LockMachine(g_pSession, LockType_Shared), VERR_ACCESS_DENIED);
-
     do
     {
-
-        /* Get the associated console. */
-        ComPtr<IConsole> console;
-        CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam()));
-
         /* Query the machine's state to avoid unnecessary IPC. */
         MachineState_T machineState;
-        CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
+        CHECK_ERROR_BREAK(machine, COMGETTER(State)(&machineState));
+
         if (   machineState == MachineState_Running
             || machineState == MachineState_Paused)
         {
-            ComPtr<IProgress> progress;
-
-            switch (enmResp)
+            /* Open a session for the VM. */
+            CHECK_ERROR_BREAK(machine, LockMachine(g_pSession, LockType_Shared));
+
+            do
             {
-                case APIMON_RESPONSE_POWEROFF:
-                    CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
-                    serviceLogVerbose(("apimon: Waiting for powering off machine \"%ls\" ...\n",
-                                       strUuid.raw()));
-                    progress->WaitForCompletion(ulTimeout);
-                    CHECK_PROGRESS_ERROR(progress, ("Failed to power off machine \"%ls\"",
-                                         strUuid.raw()));
-                    break;
-
-                case APIMON_RESPONSE_SAVE:
+                /* Get the associated console. */
+                ComPtr<IConsole> console;
+                CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam()));
+
+                ComPtr<IProgress> progress;
+
+                switch (enmResp)
                 {
-                    /* First pause so we don't trigger a live save which needs more time/resources. */
-                    bool fPaused = false;
-                    rc = console->Pause();
-                    if (FAILED(rc))
+                    case APIMON_RESPONSE_PAUSE:
+                        if (machineState != MachineState_Paused)
+                        {
+                            serviceLogVerbose(("apimon: Pausing machine \"%ls\" ...\n",
+                                               strUuid.raw()));
+                            CHECK_ERROR_BREAK(console, Pause());
+                        }
+                        break;
+
+                    case APIMON_RESPONSE_POWEROFF:
+                        serviceLogVerbose(("apimon: Powering off machine \"%ls\" ...\n",
+                                           strUuid.raw()));
+                        CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
+                        progress->WaitForCompletion(ulTimeout);
+                        CHECK_PROGRESS_ERROR(progress, ("Failed to power off machine \"%ls\"",
+                                             strUuid.raw()));
+                        break;
+
+                    case APIMON_RESPONSE_SAVE:
                     {
-                        bool fError = true;
-                        if (rc == VBOX_E_INVALID_VM_STATE)
+                        serviceLogVerbose(("apimon: Saving state of machine \"%ls\" ...\n",
+                                           strUuid.raw()));
+
+                        /* First pause so we don't trigger a live save which needs more time/resources. */
+                        bool fPaused = false;
+                        rc = console->Pause();
+                        if (FAILED(rc))
                         {
-                            /* Check if we are already paused. */
-                            CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
-                            /* The error code was lost by the previous instruction. */
-                            rc = VBOX_E_INVALID_VM_STATE;
-                            if (machineState != MachineState_Paused)
+                            bool fError = true;
+                            if (rc == VBOX_E_INVALID_VM_STATE)
                             {
-                                serviceLog("apimon: Machine \"%s\" in invalid state %d -- %s\n",
-                                           strUuid.raw(), machineState, apimonMachineStateToName(machineState, false));
+                                /* Check if we are already paused. */
+                                CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
+                                /* The error code was lost by the previous instruction. */
+                                rc = VBOX_E_INVALID_VM_STATE;
+                                if (machineState != MachineState_Paused)
+                                {
+                                    serviceLog("apimon: Machine \"%ls\" in invalid state %d -- %s\n",
+                                               strUuid.raw(), machineState, apimonMachineStateToName(machineState, false));
+                                }
+                                else
+                                {
+                                    fError = false;
+                                    fPaused = true;
+                                }
                             }
-                            else
-                            {
-                                fError = false;
-                                fPaused = true;
-                            }
+                            if (fError)
+                                break;
                         }
-                        if (fError)
+
+                        CHECK_ERROR(console, SaveState(progress.asOutParam()));
+                        if (FAILED(rc))
+                        {
+                            if (!fPaused)
+                                console->Resume();
                             break;
-                    }
-
-                    serviceLogVerbose(("apimon: Waiting for saving state of machine \"%ls\" ...\n",
-                                       strUuid.raw()));
-
-                    CHECK_ERROR(console, SaveState(progress.asOutParam()));
-                    if (FAILED(rc))
-                    {
-                        if (!fPaused)
-                            console->Resume();
+                        }
+
+                        progress->WaitForCompletion(ulTimeout);
+                        CHECK_PROGRESS_ERROR(progress, ("Failed to save machine state of machine \"%ls\"",
+                                             strUuid.raw()));
+                        if (FAILED(rc))
+                        {
+                            if (!fPaused)
+                                console->Resume();
+                        }
+
                         break;
                     }
 
-                    progress->WaitForCompletion(ulTimeout);
-                    CHECK_PROGRESS_ERROR(progress, ("Failed to save machine state of machine \"%ls\"",
-                                         strUuid.raw()));
-                    if (FAILED(rc))
-                    {
-                        if (!fPaused)
-                            console->Resume();
-                    }
-
-                    break;
+                    case APIMON_RESPONSE_SHUTDOWN:
+                        serviceLogVerbose(("apimon: Shutting down machine \"%ls\" ...\n", strUuid.raw()));
+                        CHECK_ERROR_BREAK(console, PowerButton());
+                        break;
+
+                    default:
+                        AssertMsgFailed(("Response %d not implemented", enmResp));
+                        break;
                 }
-
-                case APIMON_RESPONSE_SHUTDOWN:
-                    CHECK_ERROR_BREAK(console, PowerButton());
-                    serviceLogVerbose(("apimon: Waiting for shutdown of machine \"%ls\" ...\n",
-                                       strUuid.raw()));
-                    progress->WaitForCompletion(ulTimeout);
-                    CHECK_PROGRESS_ERROR(progress, ("Failed to shutdown machine \"%ls\"",
-                                         strUuid.raw()));
-                    break;
-
-                default:
-                    AssertMsgFailed(("Response %d not implemented", enmResp));
-                    break;
-            }
+            } while (0);
+
+            /* Unlock the machine again. */
+            g_pSession->UnlockMachine();
         }
         else
-            serviceLog("apimon: Machine \"%s\" is in invalid state \"%s\" (%d) for triggering \"%s\"\n",
-                       strUuid.raw(), apimonMachineStateToName(machineState, false), machineState,
-                       apimonResponseToStr(enmResp));
+            serviceLogVerbose(("apimon: Warning: Could not trigger \"%s\" (%d) for machine \"%ls\"; in state \"%s\" (%d) currently\n",
+                               apimonResponseToStr(enmResp), enmResp, strUuid.raw(),
+                               apimonMachineStateToName(machineState, false), machineState));
     } while (0);
 
-    /* Unlock the machine again. */
-    g_pSession->UnlockMachine();
+
 
     return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_COM_IPRT_ERROR;
@@ -342,7 +363,7 @@
             {
                 int rc2 = apimonMachineControl(it->first /* Uuid */,
-                                               &it->second /* Machine */, enmResp, g_ulAPIMonTriggerTimeoutMS);
+                                               &it->second /* Machine */, enmResp, g_ulAPIMonResponseTimeoutMS);
                 if (RT_FAILURE(rc2))
-                    serviceLog("apimon: Controlling machine \"%ls\" (action: %s) failed with rc=%Rrc",
+                    serviceLog("apimon: Controlling machine \"%ls\" (response \"%s\") failed with rc=%Rrc",
                                it->first.raw(), apimonResponseToStr(enmResp), rc);
 
@@ -411,8 +432,8 @@
                 break;
 
-            case GETOPTDEF_APIMON_TRIGGER_TIMEOUT:
-                g_ulAPIMonTriggerTimeoutMS = ValueUnion.u32;
-                if (g_ulAPIMonTriggerTimeoutMS < 5000) /* Don't allow timeouts < 5s. */
-                    g_ulAPIMonTriggerTimeoutMS = 5000;
+            case GETOPTDEF_APIMON_RESP_TIMEOUT:
+                g_ulAPIMonResponseTimeoutMS = ValueUnion.u32;
+                if (g_ulAPIMonResponseTimeoutMS < 5000) /* Don't allow timeouts < 5s. */
+                    g_ulAPIMonResponseTimeoutMS = 5000;
                 break;
 
@@ -478,18 +499,30 @@
 
         /* Trigger timeout (in ms). */
-        if (!g_ulAPIMonTriggerTimeoutMS) /* Not set by command line? */
+        if (!g_ulAPIMonResponseTimeoutMS) /* Not set by command line? */
         {
             CHECK_ERROR_BREAK(g_pVirtualBox, GetExtraData(Bstr("Watchdog/APIMonitor/TriggerTimeout").raw(),
                                                           strValue.asOutParam()));
             if (!strValue.isEmpty())
-                g_ulAPIMonTriggerTimeoutMS = Utf8Str(strValue).toUInt32();
-        }
-        if (!g_ulAPIMonTriggerTimeoutMS) /* Still not set? Use a default. */
+                g_ulAPIMonResponseTimeoutMS = Utf8Str(strValue).toUInt32();
+        }
+        if (!g_ulAPIMonResponseTimeoutMS) /* Still not set? Use a default. */
         {
             serviceLogVerbose(("apimon: API monitor trigger timeout not given, defaulting to 30s\n"));
 
             /* Default is 30 seconds timeout. */
-            g_ulAPIMonTriggerTimeoutMS = 30 * 1000;
-        }
+            g_ulAPIMonResponseTimeoutMS = 30 * 1000;
+        }
+
+#ifdef DEBUG
+        /* Groups. */
+        serviceLogVerbose(("apimon: Handling %u groups:", g_vecAPIMonGroups.size()));
+        mapGroupsIterConst itGroups = g_vecAPIMonGroups.begin();
+        while (itGroups != g_vecAPIMonGroups.end())
+        {
+            serviceLogVerbose((" %s", itGroups->first.c_str()));
+            itGroups++;
+        }
+        serviceLogVerbose(("\n"));
+#endif
 
     } while (0);
@@ -603,13 +636,15 @@
     0 /* Not used */,
     /* pszUsage. */
-    " [--apimon-groups=<string>]\n"
+    " [--apimon-groups=<string[,stringN]>]\n"
     " [--apimon-isln-response=<cmd>] [--apimon-isln-timeout=<ms>]\n"
-    " [--apimon-trigger-timeout=<ms>]",
+    " [--apimon-resp-timeout=<ms>]",
     /* pszOptions. */
-    "--apimon-groups        Sets the VM groups for monitoring (none).\n"
-    "--apimon-isln-response Sets the isolation response (shutdown VM).\n"
+    "--apimon-groups        Sets the VM groups for monitoring (all),\n"
+    "                       comma-separated list.\n"
+    "--apimon-isln-response Sets the isolation response to one of:\n"
+    "                       none, pause, poweroff, save, shutdown\n"
+    "                       (none).\n"
     "--apimon-isln-timeout  Sets the isolation timeout in ms (30s).\n"
-    "--apimon-trigger-timeout\n"
-    "                       Sets the trigger timeout in ms (30s).\n",
+    "--apimon-resp-timeout  Sets the response timeout in ms (30s).\n",
     /* methods. */
     VBoxModAPIMonitorPreInit,
Index: /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp	(revision 41359)
+++ /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp	(revision 41360)
@@ -491,5 +491,8 @@
 {
     PVBOXWATCHDOG_MACHINE pMachine = getMachine(strUuid);
-    AssertPtrReturn(pMachine, VERR_INVALID_PARAMETER);
+    /* Note: The machine state will change to "setting up" when machine gets deleted,
+     *       so pMachine might be NULL here. */
+    if (!pMachine)
+        return VINF_SUCCESS;
 
     return balloonMachineUpdate(strUuid, pMachine);
Index: /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp	(revision 41359)
+++ /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp	(revision 41360)
@@ -387,5 +387,5 @@
             else
                 itGroups->second.push_back(strUuid);
-            serviceLogVerbose(("Group \"%ls\" now has %ld machine(s)\n",
+            serviceLogVerbose(("Group \"%s\" has now %ld machine(s)\n",
                                itGroup->first.c_str(), itGroups->second.size()));
             itGroup++;
