ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WSL 容器 SDK 中 WslcStopContainer 的完整使用指南:从停止信号、超时语义到源码级实现

WSL 容器 SDK 中 WslcStopContainer 的完整使用指南:从停止信号、超时语义到源码级实现 WSL 容器 SDK 中 WslcStopContainer 的完整使用指南从停止信号、超时语义到源码级实现【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL导读WslcStopContainer是 Windows Subsystem for LinuxWSL容器 SDKWslcSDK中用于停止 WSL 容器的核心 C 语言 API。它允许调用方以可控的方式向运行中的容器发送 Linux 信号如 SIGTERM、SIGKILL并指定超时时间是容器生命周期管理创建 → 启动 → 停止 → 删除中承上启下的关键一环。读完本文你将掌握WslcStopContainer的完整签名与参数语义、WslcSignal枚举的取值与选择策略、超时参数的隐藏细节并通过仓库源码理解其内部调用链与错误处理机制能够在自己的 WSL 容器管理程序中正确、安全地停止容器。一、API 概览签名与参数语义WslcStopContainer的原型定义于 WslcSDK 公共头文件 src/windows/WslcSDK/wslcsdk.h并通过 src/windows/WslcSDK/wslcsdk.def 导出为 SDK 公开符号STDAPI WslcStopContainer(_In_ WslcContainer container, _In_ WslcSignal signal, _In_ uint32_t timeoutSeconds, _Outptr_opt_result_z_ PWSTR* errorMessage);参数明细参数类型方向说明containerWslcContainerin要停止的容器的句柄。该句柄由WslcCreateContainer或WslcOpenContainer创建停止操作完成后仍需调用WslcReleaseContainer释放signalWslcSignalin发送给容器 init 进程的信号决定停止方式优雅退出或强制终止详见下文枚举说明timeoutSecondsuint32_tin等待容器停止的超时秒数0表示立即超时WSLC_STOP_TIMEOUT_NONE表示无限等待errorMessagePWSTR*out, optional返回失败时的详细错误消息UTF-16 字符串可传NULL忽略返回的字符串由调用方负责通过CoTaskMemFree释放返回值类型为HRESULT成功返回S_OK失败返回相应的错误码如WSLC_E_CONTAINER_NOT_RUNNING或E_INVALIDARG。从源码结构看WslcContainer是一个不透明句柄在 wslcsdk.h 中通过DECLARE_HANDLE(WslcContainer)声明调用方不应直接解引用它所有对容器的操作都应经由 SDK API 完成。原文档示例原文档给出了最基本的调用形式向容器发送SIGTERM超时 30 秒不接收错误消息HRESULT hr WslcStopContainer( container, WSLC_SIGNAL_SIGTERM, (uint32_t)30, NULL);二、信号枚举 WslcSignal优雅停止与强制终止的选择WslcSignal枚举完整定义于 src/windows/WslcSDK/wslcsdk.h其取值与标准 POSIX 信号编号一一对应枚举值数值语义WSLC_SIGNAL_NONE0不发信号仅触发停止流程与超时配合使用见下文超时语义WSLC_SIGNAL_SIGHUP1SIGHUP挂断 / 重载配置WSLC_SIGNAL_SIGINT2SIGINT中断等效于 Ctrl-CWSLC_SIGNAL_SIGQUIT3SIGQUIT退出并产生 core dumpWSLC_SIGNAL_SIGKILL9SIGKILL立即强制终止不可被捕获或忽略WSLC_SIGNAL_SIGTERM15SIGTERM优雅关闭进程默认行为是退出但可自行处理善后选择策略首选WSLC_SIGNAL_SIGTERM15给予容器内 init 进程优雅退出的机会让其完成资源清理、刷盘、通知子进程等善后工作。这与原文档示例的默认选择一致。兜底WSLC_SIGNAL_SIGKILL9当容器内的进程无响应、无法优雅退出时SIGKILL 可确保立即终止。注意 SIGKILL 无法被进程捕获容器内的数据可能来不及落盘。WSLC_SIGNAL_NONE0配合超时使用发送任何信号仅等待容器按自身配置的停止超时StopTimeout自行退出。仓库测试 test/windows/WSLCTests.cpp 展示了WslcSignalNone, 0这一组合用于验证“以 0 秒超时覆盖容器默认停止超时”的语义。三、超时参数 timeoutSeconds 的深层语义timeoutSeconds是uint32_t类型其取值在仓库测试与 WinRT 封装中表现出三种语义0立即超时不等待容器退出立即返回。注意测试中有一条关键验证即使容器配置了非零的默认停止超时传入0也会覆盖默认值见 test/windows/WSLCTests.cpp 的注释 Validate that passing 0 as the stop timeout overrides the default。WSLC_STOP_TIMEOUT_NONE无限等待表示不设置超时上限一直等待容器停止完成。测试 test/windows/WSLCTests.cpp 中通过container.Get().Stop(WSLCSignalSIGTERM, WSLC_STOP_TIMEOUT_NONE)验证了这一模式。任意正整数秒等待指定秒数后若容器仍未停止则超时返回。从源码结构推断WSLC_STOP_TIMEOUT_NONE的定义可在测试文件 test/windows/WSLCTests.cpp 及 Launcher 相关实现中找到用于区分“0 秒立即超时”与“无限等待”两种截然不同的语义——这是调用此 API 时最容易踩坑的地方务必区分清楚。WinRT 层的超时校验在 WinRT 封装层 src/windows/WslcSDK/winrt/Container.cpp 中Container::Stop先将Windows.Foundation.TimeSpan转换为秒再进行两项前置校验void Container::Stop(winrt::Microsoft::WSL::Containers::Signal const signal, TimeSpan timeout) { wil::unique_cotaskmem_string errorMessage; auto timeoutSeconds std::chrono::duration_caststd::chrono::seconds(timeout).count(); if (timeoutSeconds std::numeric_limitsuint32_t::max()) { throw winrt::hresult_invalid_argument(LTimeout is too large); } if (timeoutSeconds 0) { throw winrt::hresult_invalid_argument(LTimeout must be non-negative); } auto hr WslcStopContainer(ToHandle(), static_castWslcSignal(signal), static_castuint32_t(timeoutSeconds), errorMessage.put()); THROW_MSG_IF_FAILED(hr, errorMessage); }这提示我们在直接使用 C API 时也应注意timeoutSeconds不应为负虽然uint32_t类型本身杜绝了负值且需保证在合理的范围内。超时语义与容器的StopTimeout 配置容器 inspect 输出中的Config.StopTimeout字段相互关联测试 test/windows/WSLCTests.cpp 通过inspect.Config.StopTimeout断言了配置的生效情况。四、源码级实现WslcStopContainer 的内部调用链WslcStopContainer的实现在 src/windows/WslcSDK/wslcsdk.cppSTDAPI WslcStopContainer(_In_ WslcContainer container, _In_ WslcSignal signal, _In_ uint32_t timeoutSeconds, _Outptr_opt_result_z_ PWSTR* errorMessage) try { ErrorInfoWrapper errorInfoWrapper{errorMessage}; auto internalType CheckAndGetInternalType(container); RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType-container); return errorInfoWrapper.CaptureResult(internalType-container-Stop(Convert(signal), timeoutSeconds)); } CATCH_RETURN();调用链分析错误信息封装ErrorInfoWrapper errorInfoWrapper{errorMessage}负责将底层失败转换为调用方可读取的 UTF-16 错误消息若调用方传入NULL则静默忽略错误详情。句柄合法性校验CheckAndGetInternalType(container)将不透明的WslcContainer句柄转换为内部对象RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType-container)表明当内部容器对象为空即容器句柄无效或已释放时返回HRESULT_FROM_WIN32(ERROR_INVALID_STATE)即0x800713D9。信号转换与底层调用Convert(signal)将 C SDK 层的WslcSignal转换为运行时内部表示随后调用internalType-container-Stop(...)完成真正的停止动作。真正的停止逻辑包括向 init 进程发送信号、等待退出、超时控制封装在 WinRT 运行时的Container::Stop中C API 是这一能力的薄封装。与 WinRT 层的对应关系在 WinRT 层 src/windows/WslcSDK/winrt/Container.cpp 中Stop方法先完成超时参数的秒级转换与合法性校验拒绝负数与超出uint32_t范围的值再以static_castWslcSignal(signal)将 WinRT 的Signal枚举定义于 src/windows/WslcSDK/winrt/wslcsdk.idl强制转换为 C 层枚举后调用WslcStopContainer。两套 API 使用相同的枚举数值保证了语义一致enum Signal { None 0, // No signal; reserved for future use SIGHUP 1, // SIGHUP: reload / hangup SIGINT 2, // SIGINT: interrupt (Ctrl-C) SIGQUIT 3, // SIGQUIT: quit with core dump SIGKILL 9, // SIGKILL: immediate termination SIGTERM 15, // SIGTERM: graceful shutdown };五、返回值与错误处理WslcStopContainer返回HRESULT常见返回值包括返回值含义S_OK停止请求已成功处理容器已停止或按超时语义返回WSLC_E_CONTAINER_NOT_RUNNING容器当前不在运行状态无法执行停止操作HRESULT_FROM_WIN32(ERROR_INVALID_STATE)容器句柄无效或内部对象已释放如重复释放、句柄过期E_INVALIDARG参数非法WinRT 层在超时值非法时会抛出hresult_invalid_argument错误消息的使用当errorMessage非空时失败时 SDK 会通过ErrorInfoWrapper填充一条便于诊断的 UTF-16 错误字符串例如测试 test/windows/WSLCTests.cpp 中验证的Container xxx is not running.。调用方使用完毕后应通过CoTaskMemFree释放该字符串。六、仓库测试用例行为边界的实证测试文件 test/windows/WSLCTests.cpp 中包含大量针对Stop的用例可直接作为该 API 行为边界的权威参考未运行容器不可停止test/windows/WSLCTests.cpp创建后尚未启动的容器调用Stop(WSLCSignalSIGKILL, 0)返回WSLC_E_CONTAINER_NOT_RUNNING并输出错误消息Container test-container-2 is not running.。SIGTERM 优雅停止test/windows/WSLCTests.cpp对{sleep, 99999}这类长驻进程容器发送 SIGTERM容器进入WslcContainerStateExited状态且停止后可正常删除。停止超时覆盖test/windows/WSLCTests.cpp容器配置WSLC_STOP_TIMEOUT_NONE时传入0秒超时仍可覆盖默认行为并成功停止。超时边界组合包括 SIGTERM 配合WSLC_STOP_TIMEOUT_NONEtest/windows/WSLCTests.cpp、SIGKILL 配合 0 秒超时test/windows/WSLCTests.cpp等组合覆盖了优雅退出、强制终止与超时三者交叉的典型场景。对已退出容器再次 Stop 是 no-optest/windows/WSLCTests.cpp已处于 Exited 状态的容器再次调用 Stop 返回成功但状态不变。此外test/windows/PluginTests.cpp 中的container.Get().Stop(WSLCSignalSIGKILL, 0)说明该 API 也被 WSL 插件体系WslPluginApi.h中的容器封装复用进一步佐证了WslcStopContainer是停止容器的统一底层入口。七、完整的容器生命周期示例将WslcStopContainer放入完整的生命周期流程中典型调用序列为WslcContainer container NULL; HRESULT hr WslcOpenContainer(session, my-container, container, NULL); if (FAILED(hr)) { /* 打开失败 */ } // 优雅停止先给 SIGTERM等待最多 30 秒 hr WslcStopContainer(container, WSLC_SIGNAL_SIGTERM, (uint32_t)30, NULL); if (FAILED(hr)) { // 超时或失败后可升级为 SIGKILL 强制终止 hr WslcStopContainer(container, WSLC_SIGNAL_SIGKILL, (uint32_t)10, NULL); } // 停止后查询状态确认 WslcContainerState state; if (SUCCEEDED(WslcGetContainerState(container, state))) { // WSLC_CONTAINER_STATE_EXITED } // 释放句柄 WslcReleaseContainer(container);推荐实践总结先 SIGTERM、后 SIGKILL 的二级停止策略先给足优雅退出时间超时后再强制终止既保护数据完整性又保证停止可完成。明确区分0与WSLC_STOP_TIMEOUT_NONE0表示立即超时不等退出WSLC_STOP_TIMEOUT_NONE表示无限等待二者行为差异极大。不要忽略错误消息失败时读取errorMessage可快速定位问题如容器未运行、句柄失效用后通过CoTaskMemFree释放。停止后再释放句柄WslcReleaseContainer应在停止操作完成之后调用若句柄已释放WslcStopContainer会返回ERROR_INVALID_STATE。停止后容器仍可删除测试证实通过WslcStopContainer停止的容器可继续调用WslcDeleteContainer删除二者配合构成完整的清理流程。八、相关资源API 声明与WslcSignal枚举src/windows/WslcSDK/wslcsdk.hAPI 实现src/windows/WslcSDK/wslcsdk.cppWinRT 封装含超时校验src/windows/WslcSDK/winrt/Container.cppWinRTSignal枚举定义src/windows/WslcSDK/winrt/wslcsdk.idlDLL 导出符号表src/windows/WslcSDK/wslcsdk.def行为边界测试test/windows/WSLCTests.cpp 与 test/windows/PluginTests.cppSDK 容器使用概览nuget/Microsoft.WSL.Containers/docs/README.MD【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表