[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |