ShutdownMonitoring.h (4168B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include <Windows.h> 5 #include <AppInstallerProgress.h> 6 #include <winrt/Windows.ApplicationModel.h> 7 #include <wil/resource.h> 8 #include <memory> 9 #include <mutex> 10 11 namespace AppInstaller::ShutdownMonitoring 12 { 13 // Type to contain the CTRL signal and window messages handler. 14 struct TerminationSignalHandler 15 { 16 TerminationSignalHandler(); 17 18 ~TerminationSignalHandler(); 19 20 // Gets the singleton handler. 21 static std::shared_ptr<TerminationSignalHandler> Instance(); 22 23 // Add a termination listener. 24 void AddListener(ICancellable* cancellable); 25 26 // Remove a termination listener. 27 void RemoveListener(ICancellable* cancellable); 28 29 // Add or remove the listener based on `enabled`. 30 static void EnableListener(bool enabled, ICancellable* cancellable); 31 32 #ifndef AICLI_DISABLE_TEST_HOOKS 33 // Gets the window handle for the message window. 34 HWND GetWindowHandle() const; 35 36 // Waits for the shutdown event. 37 bool WaitForAppShutdownEvent() const; 38 #endif 39 40 private: 41 void StartAppShutdown(); 42 43 static BOOL WINAPI StaticCtrlHandlerFunction(DWORD ctrlType); 44 45 static LRESULT WINAPI WindowMessageProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 46 47 BOOL CtrlHandlerFunction(DWORD ctrlType); 48 49 // Terminates the currently attached contexts. 50 // Returns FALSE if no contexts attached; TRUE otherwise. 51 BOOL InformListeners(CancelReason reason, bool force); 52 53 void CreateWindowAndStartMessageLoop(); 54 55 #ifndef AICLI_DISABLE_TEST_HOOKS 56 wil::unique_event m_appShutdownEvent; 57 #endif 58 59 std::mutex m_listenersLock; 60 std::vector<ICancellable*> m_listeners; 61 wil::unique_event m_messageQueueReady; 62 wil::unique_hwnd m_windowHandle; 63 std::thread m_windowThread; 64 winrt::Windows::ApplicationModel::PackageCatalog m_catalog = nullptr; 65 decltype(winrt::Windows::ApplicationModel::PackageCatalog{ nullptr }.PackageUpdating(winrt::auto_revoke, nullptr)) m_updatingEvent; 66 }; 67 68 // Coordinates shutdown across server components 69 struct ServerShutdownSynchronization : public ICancellable 70 { 71 using ShutdownCompleteCallback = void (*)(); 72 73 // Initializes the monitoring system and sets up a callback to be invoked when shutdown is completed. 74 static void Initialize(ShutdownCompleteCallback callback); 75 76 // "Interface" for a single component to synchronize with. 77 struct ComponentSystem 78 { 79 // Initiate the shutdown process. 80 // Components are expected to set flags to prevent any further work from beginning and return as quickly as possible. 81 void (*BlockNewWork)(CancelReason reason) = nullptr; 82 83 // Components are expected to cancel active or pending work as asynchronously as possible. 84 void (*BeginShutdown)(CancelReason reason) = nullptr; 85 86 // Components wait until all active and pending work have completed their 87 void (*Wait)() = nullptr; 88 }; 89 90 // Adds a component to the system. 91 static void AddComponent(const ComponentSystem& component); 92 93 // Waits for the shutdown to complete. 94 static void WaitForShutdown(); 95 96 // Listens for a termination signal. 97 void Cancel(CancelReason reason, bool force) override; 98 99 private: 100 ServerShutdownSynchronization(); 101 ~ServerShutdownSynchronization(); 102 103 static ServerShutdownSynchronization& Instance(); 104 105 // Runs the actual shutdown process and invokes the callback. 106 void SynchronizeShutdown(CancelReason reason); 107 108 ShutdownCompleteCallback m_callback = nullptr; 109 std::mutex m_componentsLock; 110 std::vector<ComponentSystem> m_components; 111 std::mutex m_threadLock; 112 std::thread m_shutdownThread; 113 wil::slim_event_manual_reset m_shutdownComplete; 114 }; 115 }