[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Try to make sure the agent always always handles shutdown events



It seems that on Server 2008 the agent does not reliably wake up on
shutdown watch events. This does not seem to occur on any other OS so
it is likely that this is a bug in Server 2008.

To work around the problem this patch nodifies the agent wake up once a
minute and check for a shutdown event (or a suspend event, for
completeness) and act accordingly.

Also this patch squashes the uninteresting error messages that occur
when an attempt is made to read a non-existent xenstore key.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenagent/service.cpp        | 41 +++++++++++++++++++++++++++++++----------
 src/xenagent/service.h          |  5 +++--
 src/xenagent/xenifacedevice.cpp | 11 +++++++++++
 src/xenagent/xenifacedevice.h   |  1 +
 src/xeniface/ioctl_store.c      | 17 +++++++++++++----
 5 files changed, 59 insertions(+), 16 deletions(-)

diff --git a/src/xenagent/service.cpp b/src/xenagent/service.cpp
index 170c2dd..7243fa4 100644
--- a/src/xenagent/service.cpp
+++ b/src/xenagent/service.cpp
@@ -202,6 +202,7 @@ CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL),
     m_svc_stop = CreateEvent(FALSE, NULL, NULL, FALSE);
     m_evt_shutdown = CreateEvent(FALSE, NULL, NULL, FALSE);
     m_evt_suspend = CreateEvent(FALSE, NULL, NULL, FALSE);
+    m_count = 0;
 
     InitializeCriticalSection(&m_crit);
 }
@@ -315,20 +316,24 @@ void CXenAgent::OnPowerEvent(DWORD evt, LPVOID data)
 bool CXenAgent::ServiceMainLoop()
 {
     HANDLE  events[3] = { m_svc_stop, m_evt_shutdown, m_evt_suspend };
-    DWORD   wait = WaitForMultipleObjects(3, events, FALSE, INFINITE);
+    DWORD   wait = WaitForMultipleObjectsEx(3, events, FALSE, 60000, TRUE);
 
     switch (wait) {
     case WAIT_OBJECT_0:
         return false; // exit loop
 
     case WAIT_OBJECT_0+1:
-        OnShutdown();
-        return true; // continue loop
+        return !CheckShutdown();
 
     case WAIT_OBJECT_0+2:
-        OnSuspend();
+        CheckSuspend();
         return true; // continue loop
 
+    case WAIT_IO_COMPLETION:
+    case WAIT_TIMEOUT:
+        CheckSuspend();
+        return !CheckShutdown();
+
     default:
         CXenAgent::Log("WaitForMultipleObjects failed (%08x)\n", wait);
         EventLog(EVENT_XENUSER_UNEXPECTED);
@@ -488,16 +493,17 @@ void CXenAgent::SetXenTime()
 #pragma warning(push)
 #pragma warning(disable:28159)
 
-void CXenAgent::OnShutdown()
+bool CXenAgent::CheckShutdown()
 {
     CCritSec crit(&m_crit);
     if (m_device == NULL)
-        return;
+        return false;
 
     std::string type;
-    m_device->StoreRead("control/shutdown", type);
+    if (!m_device->StoreRead("control/shutdown", type))
+        return false;
 
-    CXenAgent::Log("OnShutdown(%ws) = %s\n", m_device->Path(), type.c_str());
+    CXenAgent::Log("Shutdown(%ws) = %s\n", m_device->Path(), type.c_str());
 
     if (type == "poweroff") {
         EventLog(EVENT_XENUSER_POWEROFF);
@@ -510,6 +516,7 @@ void CXenAgent::OnShutdown()
                                       SHTDN_REASON_FLAG_PLANNED)) {
             CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", 
GetLastError());
         }
+        return true;
     } else if (type == "reboot") {
         EventLog(EVENT_XENUSER_REBOOT);
 
@@ -521,6 +528,7 @@ void CXenAgent::OnShutdown()
                                       SHTDN_REASON_FLAG_PLANNED)) {
             CXenAgent::Log("InitiateSystemShutdownEx failed %08x\n", 
GetLastError());
         }
+        return true;
     } else if (type == "s4") {
         EventLog(EVENT_XENUSER_S4);
 
@@ -529,6 +537,7 @@ void CXenAgent::OnShutdown()
         if (!SetSystemPowerState(FALSE, FALSE)) {
             CXenAgent::Log("SetSystemPowerState failed %08x\n", 
GetLastError());
         }
+        return true;
     } else if (type == "s3") {
         EventLog(EVENT_XENUSER_S3);
 
@@ -537,18 +546,30 @@ void CXenAgent::OnShutdown()
         if (!SetSuspendState(FALSE, TRUE, FALSE)) {
             CXenAgent::Log("SetSuspendState failed %08x\n", GetLastError());
         }
+        return true;
     }
+
+    return false;
 }
 
 #pragma warning(pop)
 
-void CXenAgent::OnSuspend()
+void CXenAgent::CheckSuspend()
 {
     CCritSec crit(&m_crit);
     if (m_device == NULL)
         return;
 
-    CXenAgent::Log("OnSuspend(%ws)\n", m_device->Path());
+    DWORD count = 0;
+
+    if (!m_device->SuspendGetCount(&count))
+        return;
+
+    if (m_count == count)
+        return;
+
+    CXenAgent::Log("Suspend(%ws)\n", m_device->Path());
+
     EventLog(EVENT_XENUSER_UNSUSPENDED);
 
     // recreate shutdown watch, as suspending deactivated the watch
diff --git a/src/xenagent/service.h b/src/xenagent/service.h
index ad9821a..765887c 100644
--- a/src/xenagent/service.h
+++ b/src/xenagent/service.h
@@ -79,8 +79,8 @@ private: // helpers
     void AdjustXenTimeToUTC(FILETIME* time);
     bool RegCheckIsUTC(const char* path);
     void SetXenTime();
-    void OnShutdown();
-    void OnSuspend();
+    bool CheckShutdown();
+    void CheckSuspend();
 
 private: // service support
     void SetServiceStatus(DWORD state, DWORD exit = 0, DWORD hint = 0);
@@ -99,6 +99,7 @@ private: // service support
     CRITICAL_SECTION        m_crit;
     void*                   m_ctxt_shutdown;
     void*                   m_ctxt_suspend;
+    DWORD                   m_count;
 };
 
 #endif
diff --git a/src/xenagent/xenifacedevice.cpp b/src/xenagent/xenifacedevice.cpp
index 98e4d2f..c254b9a 100644
--- a/src/xenagent/xenifacedevice.cpp
+++ b/src/xenagent/xenifacedevice.cpp
@@ -138,6 +138,17 @@ bool CXenIfaceDevice::SuspendDeregister(void* ctxt)
                  NULL, 0);
 }
 
+bool CXenIfaceDevice::SuspendGetCount(DWORD *count)
+{
+    DWORD out;
+    if (!Ioctl(IOCTL_XENIFACE_SUSPEND_GET_COUNT,
+                NULL, 0,
+                &out, (DWORD)sizeof(out)))
+        return false;
+    *count = out;
+    return true;
+}
+
 // sharedinfo interface
 bool CXenIfaceDevice::SharedInfoGetTime(FILETIME* time)
 {
diff --git a/src/xenagent/xenifacedevice.h b/src/xenagent/xenifacedevice.h
index 163b193..7ea2f0e 100644
--- a/src/xenagent/xenifacedevice.h
+++ b/src/xenagent/xenifacedevice.h
@@ -52,6 +52,7 @@ public: // store interface
 public: // suspend interface
     bool SuspendRegister(HANDLE evt, void** ctxt);
     bool SuspendDeregister(void* ctxt);
+    bool SuspendGetCount(DWORD *count);
 
 public: // sharedinfo interface
     bool SharedInfoGetTime(FILETIME* time);
diff --git a/src/xeniface/ioctl_store.c b/src/xeniface/ioctl_store.c
index 1725e06..b8ee073 100644
--- a/src/xeniface/ioctl_store.c
+++ b/src/xeniface/ioctl_store.c
@@ -102,6 +102,7 @@ IoctlStoreRead(
     NTSTATUS    status;
     PCHAR       Value;
     ULONG       Length;
+    BOOLEAN     SquashError = FALSE;
 
     status = STATUS_INVALID_BUFFER_SIZE;
     if (InLen == 0)
@@ -112,8 +113,12 @@ IoctlStoreRead(
         goto fail2;
 
     status = XENBUS_STORE(Read, &Fdo->StoreInterface, NULL, NULL, Buffer, 
&Value);
-    if (!NT_SUCCESS(status))
+    if (!NT_SUCCESS(status)) {
+        if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+            SquashError = TRUE;
+
         goto fail3;
+    }
 
     Length = (ULONG)strlen(Value) + 1;
 
@@ -142,11 +147,15 @@ fail4:
     XenIfaceDebugPrint(ERROR, "Fail4 (\"%s\")=(%d < %d)\n", Buffer, OutLen, 
Length);
     XENBUS_STORE(Free, &Fdo->StoreInterface, Value);
 fail3:
-    XenIfaceDebugPrint(ERROR, "Fail3 (\"%s\")\n", Buffer);
+    if (!SquashError)
+        XenIfaceDebugPrint(ERROR, "Fail3 (\"%s\")\n", Buffer);
 fail2:
-    XenIfaceDebugPrint(ERROR, "Fail2\n");
+    if (!SquashError)
+        XenIfaceDebugPrint(ERROR, "Fail2\n");
 fail1:
-    XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status);
+    if (!SquashError)
+        XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status);
+
     return status;
 }
 
-- 
2.5.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.