拓冰建站拓冰建站
首页 / 资讯中心 / 正文

深入解析 WSL 容器 SDK 的 SessionTerminationHandler 委托与 Session::Terminated 终止事件

深入解析 WSL 容器 SDK 的 SessionTerminationHandler 委托与 Session::Terminated 终止事件【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWSL 容器WSLC会话的SessionTerminationHandler是 C/WinRT 侧监听容器会话被终止这一关键生命周期的委托类型它通过Session::Terminated事件向调用方回传一个SessionTerminationReason枚举用于区分正常关闭与异常崩溃两类终止原因。本文以 sessionterminationhandler.md 为骨架结合仓库中 WslcSDK 的 WinRT 封装源码Session.cpp、Session.h与单元测试WslcSdkWinRTTests.cpp讲清委托的定义、事件的注册/注销、终止原因枚举的底层映射以及如何基于Terminated事件实现可靠的会话清理逻辑。1. 委托与事件概览在 WSL 容器 SDK 的 WinRT 投影中SessionTerminationHandler属于 Delegates and Events 一组回调类型之一同组还有ProcessCrashHandler、ProcessOutputHandler、ProcessExitHandler。它的唯一职责是作为Session::Terminated事件的事件处理函数在会话生命周期结束的那一刻被触发。从 wslcsdk.idl 的 IDL 定义可以看到委托与事件的正式声明// src/windows/WslcSDK/winrt/wslcsdk.idl (节选) delegate void SessionTerminationHandler(SessionTerminationReason reason); // ... event SessionTerminationHandler Terminated; // 定义在 Session 运行时类上对应的 C/WinRT 使用方式即官方文档给出的最小示例session.Terminated([](SessionTerminationReason reason) { printf(terminated: %d\n, static_castint(reason)); });要点委托接收一个参数SessionTerminationReason reasonTerminated是Session类的实例事件只会在会话终止时触发一次由于回调在 WinRT 事件上下文中执行建议在回调内只做轻量处理如置位状态、唤醒等待线程把耗时清理逻辑移出回调。2. SessionTerminationReason三种终止原因SessionTerminationHandler的回调参数SessionTerminationReason是一个 WinRT 枚举定义同样位于 wslcsdk.idl 中其取值与底层 C 枚举WslcSessionTerminationReason一一对应见 sessionterminationreason.md 与 wslcsessionterminationreason.mdWinRT 枚举底层 C 值语义Unknown0WSLC_SESSION_TERMINATION_REASON_UNKNOWN无法确定的终止原因Shutdown1WSLC_SESSION_TERMINATION_REASON_SHUTDOWN会话被正常关闭如调用Terminate()Crashed2WSLC_SESSION_TERMINATION_REASON_CRASHED会话异常崩溃2.1 枚举值从 C 到 WinRT 的直接映射文档明确指出Session::OnTerminated会把WslcSessionTerminationReason直接转换为 WinRT 枚举不做任何重映射。这一实现事实可以在 Session.cpp 的线程池回调中验证void CALLBACK Session::OnTerminated(PTP_CALLBACK_INSTANCE /* instance */, PVOID context, PTP_WAIT /* wait */, TP_WAIT_RESULT /* waitResult */) noexcept { try { auto session static_castSession*(context); WslcSessionTerminationReason reason WSLC_SESSION_TERMINATION_REASON_UNKNOWN; LOG_IF_FAILED(WslcGetSessionTerminationReason(session-m_session.get(), reason)); session-m_terminatedEvent(static_castSessionTerminationReason(reason)); } CATCH_LOG(); }因此在 C 侧判断崩溃时可参考枚举文档中的等价写法通过值2判定或直接使用枚举名session.Terminated([](SessionTerminationReason reason) { if (reason static_castSessionTerminationReason(2)) { // crashed会话异常退出需要做恢复/重试处理 } });2.2 底层 C API 的取值来源reason的实际取值来自 SDK 的 C 接口WslcGetSessionTerminationReason声明见 wslcgetsessionterminationreason.mdSTDAPI WslcGetSessionTerminationReason(_In_ WslcSession session, _Out_ WslcSessionTerminationReason* reason);参数类型方向sessionWslcSessioninreasonWslcSessionTerminationReason*out返回值类型为HRESULT。在 Session.cpp 中调用失败仅通过LOG_IF_FAILED记录日志reason仍保持初始值WSLC_SESSION_TERMINATION_REASON_UNKNOWN——这也解释了为什么Unknown被设计为枚举的默认兜底值保证回调总能收到一个合法枚举。3. 事件触发的底层机制从终止句柄到线程池回调Session::Terminated并非在调用Terminate()的线程上同步触发而是基于 Windows 线程池等待机制实现的异步事件。完整链路如下对应 Session.cpp 的Start()与 Session.h 的成员设计Session::Start()调用WslcCreateSession创建底层会话句柄调用WslcGetSessionTerminationEvent拿到会话的终止事件句柄m_terminationEvent通过CreateThreadpoolWait(Session::OnTerminated, this, nullptr)创建线程池等待对象并用SetThreadpoolWait将该句柄与线程池等待关联一旦底层会话终止、终止句柄被置位线程池调度Session::OnTerminated回调回调内部查询终止原因见 2.2 节并通过m_terminatedEvent(...)广播给所有已注册的SessionTerminationHandler。// Session.h 中的关键成员 winrt::eventwinrt::Microsoft::WSL::Containers::SessionTerminationHandler m_terminatedEvent; // Bridges the one-off termination event surfaced by the SDK to the WinRT Terminated event. wil::unique_handle m_terminationEvent; wil::unique_threadpool_wait m_terminationWait;这段实现有两个值得注意的设计点一次性的终止信号终止事件在会话生命周期内只置位一次因此Terminated事件天然具有只触发一次的语义回调线程为线程池工作线程处理函数不要执行阻塞式操作也不要在回调中直接销毁Session对象本身以免与 SDK 内部的Close()/ 引用计数清理final_release产生竞争。4. 事件的注册与注销SessionTerminationHandler对应的事件访问器在 Session.h 中声明为标准的 C/WinRT 事件对winrt::event_token Terminated(winrt::Microsoft::WSL::Containers::SessionTerminationHandler const handler); void Terminated(winrt::event_token const token) noexcept;其实现位于 Session.cpp本质上是把委托注册进winrt::event容器并返回winrt::event_tokenwinrt::event_token Session::Terminated(winrt::Microsoft::WSL::Containers::SessionTerminationHandler const handler) { return m_terminatedEvent.add(handler); } void Session::Terminated(winrt::event_token const token) noexcept { m_terminatedEvent.remove(token); }因此完整的使用模式应包括注册、业务逻辑与注销推荐 RAII 或与对象生命周期绑定的注销方式// 注册保存返回的 token 以便后续注销 winrt::event_token token session.Terminated([](SessionTerminationReason reason) { if (reason SessionTerminationReason::Crashed) { // 会话崩溃记录日志、触发告警或自动重启逻辑 printf(session crashed\n); } else if (reason SessionTerminationReason::Shutdown) { // 正常关闭执行资源清理、保存状态 printf(session shut down gracefully\n); } }); // ... 运行期间执行业务逻辑 ... // 注销在释放 Session 或不再需要回调时移除处理函数 session.Terminated(token);5. 完整实战示例监听优雅关闭并区分崩溃将前文内容组合为一个可直接运行的 C/WinRT 代码骨架#include winrt/Microsoft.WSL.Containers.h #include chrono using namespace winrt::Microsoft::WSL::Containers; using namespace winrt::Windows::Foundation; int main() { // 1. 构造会话设置并启动 SessionSettings settings(Lmy-wslc-session, LC:\\wslc-storage); settings.Timeout(std::chrono::duration_castTimeSpan(std::chrono::seconds(30))); Session session(settings); // 2. 注册终止处理函数 session.Terminated([](SessionTerminationReason reason) { switch (reason) { case SessionTerminationReason::Unknown: printf(terminated: unknown reason\n); break; case SessionTerminationReason::Shutdown: printf(terminated: graceful shutdown\n); break; case SessionTerminationReason::Crashed: printf(terminated: crashed, schedule recovery\n); break; } }); session.Start(); // 3. 正常终止会话触发 Terminated 事件reason Shutdown session.Terminate(); return 0; }5.1 来自测试用例的实证仓库的 WinRT SDK 测试 WslcSdkWinRTTests.cppTerminationHandler用例完整验证了上述行为WSLC_TEST_METHOD(TerminationHandler) { // Positive: Terminating the session must trigger a graceful shutdown and fire the event std::promiseWSLCSDK::SessionTerminationReason promise; const std::filesystem::path extraStorage m_storagePath / wslc-winrt-termh-storage; auto settings WSLCSDK::SessionSettings(Lwslc-winrt-termh, extraStorage.wstring()); settings.Timeout(std::chrono::duration_castTimeSpan(30s)); auto session WSLCSDK::Session(settings); session.Terminated( { promise.set_value(reason); }); session.Start(); session.Terminate(); auto future promise.get_future(); VERIFY_ARE_EQUAL(future.wait_for(30s), std::future_status::ready); VERIFY_ARE_EQUAL(future.get(), WSLCSDK::SessionTerminationReason::Shutdown); }该测试印证了两个关键结论正常Terminate()会触发事件Terminate()之后 30 秒内测试设定的会话超时事件必然触发正常关闭对应Shutdown回调收到的终止原因为SessionTerminationReason::Shutdown与 sessionterminationreason.md 中的取值说明一致。测试还展示了另一个实战要点先注册Terminated处理函数、再调用Start()。这样能保证不会错过会话启动后立即发生的终止信号该事件基于一次性终止句柄错过即无法补收。6. 跨语言与跨层次对照SessionTerminationHandler并非 C/WinRT 独有理解它在整个 SDK 中的位置有助于正确排查问题C/WinRT 层SessionTerminationHandler委托 Session::Terminated事件本文主题枚举为SessionTerminationReasonC# 层对应文档见 csharp/delegates-and-events.md 与 csharp/sessionterminationreason.md枚举语义与 C 完全一致C 层底层 API 为WslcGetSessionTerminationReasonwslcgetsessionterminationreason.md枚举为WslcSessionTerminationReasonwslcsessionterminationreason.md。从架构上看Session类完整成员清单见 cpp/core-classes/session.md同时暴露Terminated与ProcessCrashed两个生命周期相关事件前者表示会话整体退出含正常与崩溃后者用于在崩溃时提供转储信息回调ProcessCrashHandler。若需在崩溃场景下拿到更详细的诊断数据可将两个事件配合使用ProcessCrashed负责取证Terminated负责统一收尾。7. 小结与最佳实践SessionTerminationHandler是 WSL 容器会话生命周期管理的最小但关键一环。围绕它本文梳理出以下可落地的实践结论区分终止原因SessionTerminationReason只有Unknown(0)、Shutdown(1)、Crashed(2)三档Crashed场景应触发恢复逻辑Shutdown场景执行常规清理先注册后启动在Start()之前完成Terminated注册避免错过一次性终止信号回调保持轻量OnTerminated运行在线程池工作线程上回调内只做置位/唤醒等快速操作妥善注销保存winrt::event_token并在对象销毁前调用Terminated(token)移除处理函数善用枚举兜底底层查询失败时reason恒为Unknown业务逻辑务必对该分支做默认处理。相关阅读委托与事件目录 delegates-and-events/index.md 中还有ProcessCrashHandler、ProcessOutputHandler、ProcessExitHandler等配套委托它们共同构成了 WSL 容器进程与会话回调的完整事件体系。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门