]> xenbits.xensource.com Git - people/pauldu/xeniface.git/commitdiff
xenagent: re-register shutdown watch after resume from S4
authorPaul Durrant <paul.durrant@citrix.com>
Mon, 1 Aug 2016 14:24:53 +0000 (15:24 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Mon, 1 Aug 2016 14:24:53 +0000 (15:24 +0100)
When xenagent resumes in a VM that was put into S4 it needs to re-
register the watch on control/shutdown and re-advertise all
control/feature-XXX flags.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
src/xenagent/devicelist.cpp
src/xenagent/devicelist.h
src/xenagent/service.cpp
src/xenagent/service.h

index 6b379e22e49bd2fc7984a6d5032f30f92b0378f4..7053a96a0b5faced2f06b6511a844b92eda974aa 100644 (file)
@@ -237,6 +237,28 @@ void CDeviceList::OnDeviceEvent(DWORD evt, LPVOID data)
     }
 }
 
+void CDeviceList::OnPowerEvent(DWORD evt, LPVOID data)
+{
+    switch (evt) {
+    case PBT_APMRESUMESUSPEND:
+    for (DeviceMap::iterator it = m_devs.begin();
+         it != m_devs.end();
+         ++it)
+        m_impl->OnDeviceResume(it->second);
+    break;
+
+    case PBT_APMSUSPEND:
+    for (DeviceMap::iterator it = m_devs.begin();
+         it != m_devs.end();
+         ++it)
+        m_impl->OnDeviceSuspend(it->second);
+    break;
+
+    default:
+        break;
+    }
+}
+
 CDevice* CDeviceList::GetFirstDevice()
 {
     DeviceMap::iterator it = m_devs.begin();
index ee1d8abd12e18fe549367526596c3bf2ca3df4bb..893bd4343a5ac9c0b5ef531e0e932d95b72b228c 100644 (file)
@@ -63,6 +63,8 @@ public:
     virtual CDevice* Create(const wchar_t* path) = 0;
     virtual void OnDeviceAdded(CDevice* dev) = 0;
     virtual void OnDeviceRemoved(CDevice* dev) = 0;
+    virtual void OnDeviceSuspend(CDevice* dev) = 0;
+    virtual void OnDeviceResume(CDevice* dev) = 0;
 };
 
 class CDeviceList
@@ -74,6 +76,7 @@ public:
     bool Start(HANDLE svc, IDeviceCreator* impl);
     void Stop();
     void OnDeviceEvent(DWORD evt, LPVOID data);
+    void OnPowerEvent(DWORD evt, LPVOID data);
     CDevice* GetFirstDevice();
 
 private:
index 6132fe06d7321cdc3caf1fa27d29fa66fc0a986a..2d06008d6e6514b8f4b9785fc00498b955b20f4d 100644 (file)
@@ -187,7 +187,9 @@ CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL),
 {
     m_status.dwServiceType        = SERVICE_WIN32;
     m_status.dwCurrentState       = SERVICE_START_PENDING;
-    m_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+    m_status.dwControlsAccepted   = SERVICE_ACCEPT_STOP |
+                                    SERVICE_ACCEPT_SHUTDOWN |
+                                    SERVICE_ACCEPT_POWEREVENT;
     m_status.dwWin32ExitCode      = 0;
     m_status.dwServiceSpecificExitCode = 0;
     m_status.dwCheckPoint         = 0;
@@ -214,6 +216,34 @@ CXenAgent::~CXenAgent()
     return new CXenIfaceDevice(path);
 }
 
+void CXenAgent::StartShutdownWatch()
+{
+    if (m_ctxt_shutdown)
+        return;
+
+    m_device->StoreAddWatch("control/shutdown", m_evt_shutdown, &m_ctxt_shutdown);
+
+    m_device->StoreWrite("control/feature-poweroff", "1");
+    m_device->StoreWrite("control/feature-reboot", "1");
+    m_device->StoreWrite("control/feature-s3", "1");
+    m_device->StoreWrite("control/feature-s4", "1");
+}
+
+void CXenAgent::StopShutdownWatch()
+{
+    if (!m_ctxt_shutdown)
+        return;
+
+    m_device->StoreRemove("control/feature-poweroff");
+    m_device->StoreRemove("control/feature-reboot");
+    m_device->StoreRemove("control/feature-s3");
+    m_device->StoreRemove("control/feature-s4");
+
+    m_device->StoreRemoveWatch(m_ctxt_shutdown);
+    m_ctxt_shutdown = NULL;
+}
+
+
 /*virtual*/ void CXenAgent::OnDeviceAdded(CDevice* dev)
 {
     CXenAgent::Log("OnDeviceAdded(%ws)\n", dev->Path());
@@ -222,16 +252,8 @@ CXenAgent::~CXenAgent()
     if (m_device == NULL) {
         m_device = (CXenIfaceDevice*)dev;
 
-        // shutdown
-        m_device->StoreAddWatch("control/shutdown", m_evt_shutdown, &m_ctxt_shutdown);
-        m_device->StoreWrite("control/feature-poweroff", "1");
-        m_device->StoreWrite("control/feature-reboot", "1");
-        m_device->StoreWrite("control/feature-s3", "1");
-        m_device->StoreWrite("control/feature-s4", "1");
-
-        // suspend
         m_device->SuspendRegister(m_evt_suspend, &m_ctxt_suspend);
-
+        StartShutdownWatch();
         SetXenTime();
     }
 }
@@ -242,24 +264,28 @@ CXenAgent::~CXenAgent()
 
     CCritSec crit(&m_crit);
     if (m_device == dev) {
-        // suspend
-        if (m_ctxt_suspend)
+        if (m_ctxt_suspend) {
             m_device->SuspendDeregister(m_ctxt_suspend);
-        m_ctxt_suspend = NULL;
-
-        // shutdown
-        m_device->StoreRemove("control/feature-poweroff");
-        m_device->StoreRemove("control/feature-reboot");
-        m_device->StoreRemove("control/feature-s3");
-        m_device->StoreRemove("control/feature-s4");
-        if (m_ctxt_shutdown)
-            m_device->StoreRemoveWatch(m_ctxt_shutdown);
-        m_ctxt_shutdown = NULL;
+            m_ctxt_suspend = NULL;
+        }
+        StopShutdownWatch();
 
         m_device = NULL;
     }
 }
 
+/*virtual*/ void CXenAgent::OnDeviceSuspend(CDevice* dev)
+{
+    CXenAgent::Log("OnDeviceSuspend(%ws)\n", dev->Path());
+    StopShutdownWatch();
+}
+
+/*virtual*/ void CXenAgent::OnDeviceResume(CDevice* dev)
+{
+    CXenAgent::Log("OnDeviceResume(%ws)\n", dev->Path());
+    StartShutdownWatch();
+}
+
 void CXenAgent::OnServiceStart()
 {
     CXenAgent::Log("OnServiceStart()\n");
@@ -277,6 +303,11 @@ void CXenAgent::OnDeviceEvent(DWORD evt, LPVOID data)
     m_devlist.OnDeviceEvent(evt, data);
 }
 
+void CXenAgent::OnPowerEvent(DWORD evt, LPVOID data)
+{
+    m_devlist.OnPowerEvent(evt, data);
+}
+
 bool CXenAgent::ServiceMainLoop()
 {
     HANDLE  events[3] = { m_svc_stop, m_evt_shutdown, m_evt_suspend };
@@ -577,6 +608,11 @@ DWORD WINAPI CXenAgent::__ServiceControlHandlerEx(DWORD req, DWORD evt, LPVOID d
         OnDeviceEvent(evt, data);
         return NO_ERROR;
 
+    case SERVICE_CONTROL_POWEREVENT:
+        SetServiceStatus(SERVICE_RUNNING);
+        OnPowerEvent(evt, data);
+        return NO_ERROR;
+
     case SERVICE_CONTROL_INTERROGATE:
         SetServiceStatus(SERVICE_RUNNING);
         return NO_ERROR;
index 975662b703edd2537230f11e8b82ff89c1e7c849..77a11d741ad51a7c3580bc9a8c961967fce4deaa 100644 (file)
@@ -60,14 +60,19 @@ public: // IDeviceCreator
     virtual CDevice* Create(const wchar_t* path);
     virtual void OnDeviceAdded(CDevice* dev);
     virtual void OnDeviceRemoved(CDevice* dev);
+    virtual void OnDeviceSuspend(CDevice* dev);
+    virtual void OnDeviceResume(CDevice* dev);
 
 private: // service events
     void OnServiceStart();
     void OnServiceStop();
     void OnDeviceEvent(DWORD, LPVOID);
+    void OnPowerEvent(DWORD, LPVOID);
     bool ServiceMainLoop();
 
 private: // helpers
+    void StartShutdownWatch();
+    void StopShutdownWatch();
     void AcquireShutdownPrivilege();
     void EventLog(DWORD evt);
     bool IsHostTimeUTC();