模块契约进程信号

裁剪宏:XRT_FEATURE_SIGNAL直接依赖:atomic、once、cond、thread头文件:<xrt/signal.h> 或 <xrt.h>

错误

xsignalerror 属于 xrt.signal 错误域。非法代码、平台不支持、原生 API 失败和生命周期冲突分别使用 XSIGNAL_ERROR_CODE、XSIGNAL_ERROR_UNSUPPORTED、XSIGNAL_ERROR_SYSTEM、XSIGNAL_ERROR_STATE。系统失败通过 xrtErrorSystemCode 保留 errno 或 GetLastError。

完整示例见 examples/process/signal/main.c。

信号代码

xsignal 使用跨平台稳定代码:

  • XSIGNAL_INT:交互中断;Windows 对应 SIGINT,POSIX 对应 SIGINT。
  • XSIGNAL_TERM:终止请求;对应 SIGTERM。
  • XSIGNAL_HUP:POSIX 挂断;Windows 不支持。
  • XSIGNAL_BREAK:Windows 控制台 Break;POSIX 不支持。
  • XSIGNAL_CLOSE、XSIGNAL_LOGOFF、XSIGNAL_SHUTDOWN:Windows 控制台生命周期通知;POSIX 不支持。

先用 xrtSignalSupported 判断平台能力。xrtSignalName 对已知代码返回稳定大写名称,对未知代码返回 UNKNOWN。

订阅

On 重复调度,Once 第一次入选事件快照时先变为不活动,再执行一次回调。Owned 入口只在创建成功后接管 pData,句柄最终释放时恰好调用一次析构器。监听器没有固定数量上限,调度过程不分配临时监听数组。

回调签名:

xsignalevent.Count 是本次合并批次的通知数,Total 是最近一次 xrtSignalClear 或 xrtSignalShutdown 之后的累计数,Time 是调度线程构造事件时的 XRT 时间。SystemCode 保留本批最后一个原生通知代码。

同一进程的信号回调由唯一调度线程串行执行。一个事件开始调度后新增的监听不会回看该事件。回调可以注销自身,也可以注册其他监听。

句柄生命周期

xrtSignalOff 幂等注销,但不释放调用方引用。从非调度线程调用时,它会等待该句柄已经开始的回调结束,因此返回后不会再执行该监听的用户代码。从监听自己的回调内注销不会自锁。xrtSignalFree 先注销,再释放一个引用;每次 xrtSignalRef 都需要对应一次 xrtSignalFree。

平台等待后端发生不可恢复错误时,XRT 会立即停用监听、尝试恢复原生处理方式,并把结构化错误交给进程级错误处理器。xrtSignalHealthy 返回 false 并在当前执行上下文重建同一系统错误;调用 xrtSignalShutdown 完成清理后可以重新惰性启动。

原生处理方式

Ignore 和 Restore 都会先注销对应代码的全部 XRT 监听。Restore 恢复 XRT 首次接管前保存的原生处理方式,不强行恢复为系统默认值。Raise 使用当前平台的进程内原生发送能力;如果当前处理方式是默认方式,它可能立即终止进程,因此通常只应在已经监听或明确忽略时调用。

Windows 的 INT 在 XRT 监听或忽略期间使用进程内逻辑投递,避免 GenerateConsoleCtrlEvent 把 Ctrl+C 广播到整个控制台进程组;未接管时仍使用 CRT 默认处理。Close、Logoff 和 Shutdown 没有安全的单进程程序化发送入口,xrtSignalRaise 对这些代码返回 XERR_UNSUPPORTED。这些生命周期事件还受到系统控制台处理超时约束,操作系统可能在长回调完成前终止进程,因此回调应只做快速通知,把收尾工作交给应用主流程。

计数与关闭

向 Count 或 Clear 传入 XSIGNAL_NONE 表示全部信号。待处理计数使用饱和 32 位原子数,自管道或 Windows Event 只负责唤醒,因此高频通知不会因为唤醒对象暂时已满而静默丢失。

Shutdown 注销全部监听、恢复所有原生处理方式、等待调度线程结束并释放平台唤醒资源。调度线程回调内调用会返回 XERR_STATE,避免等待自身。关闭后再次订阅会惰性创建一套新的调度资源。

xsignal类型

XRT 信号代码跨平台稳定;并非每个平台都支持全部代码。

值语义
XSIGNAL_NONE无
XSIGNAL_HUPHUP
XSIGNAL_INT有符号整数
XSIGNAL_TERMTERM
XSIGNAL_BREAKBREAK
XSIGNAL_CLOSECLOSE
XSIGNAL_LOGOFFLOGOFF
XSIGNAL_SHUTDOWN关闭调度
typedef enum xsignal { XSIGNAL_NONE = 0, XSIGNAL_HUP = 1, XSIGNAL_INT = 2, XSIGNAL_TERM = 15, XSIGNAL_BREAK = 1001, XSIGNAL_CLOSE = 1002, XSIGNAL_LOGOFF = 1003, XSIGNAL_SHUTDOWN = 1004 } xsignal;

xsignalerror类型

信号错误代码在 xrt.signal 错误域内稳定。

值语义
XSIGNAL_ERROR_CODE失败
XSIGNAL_ERROR_UNSUPPORTED不支持
XSIGNAL_ERROR_SYSTEM失败
XSIGNAL_ERROR_STATE状态非法
typedef enum xsignalerror { XSIGNAL_ERROR_CODE = 1, XSIGNAL_ERROR_UNSUPPORTED, XSIGNAL_ERROR_SYSTEM, XSIGNAL_ERROR_STATE } xsignalerror;

xsignalevent类型

一次调度可以合并多个同类原生通知,Count 是本批数量,Total 是清零后的累计数量。

字段类型语义
Codexsignal错误码
SystemCodeint32平台错误码
Countuint32数量
Totaluint64总量
Timextime时间戳(公元 UTC 毫秒)
Namecstr名称
typedef struct xsignalevent { xsignal Code; int32 SystemCode; uint32 Count; uint64 Total; xtime Time; cstr Name; } xsignalevent;

xsignalwatch类型

信号监听句柄由 XRT 引用计数管理,对外保持不透明。 不透明句柄或别名;生命周期与所有权见各使用方 API 节。

typedef struct xsignalwatch xsignalwatch;

xsignalproc类型

用户回调始终在 XRT 信号调度线程执行,不在原生信号处理上下文执行。 回调类型;参数与返回语义见签名及各使用方 API 节。

typedef void(*xsignalproc)( xsignalwatch* pWatch, const xsignalevent* pEvent, ptr pData)

xsignalfreeproc类型

Owned 监听句柄最终释放时执行数据析构器。 回调类型;参数与返回语义见签名及各使用方 API 节。

typedef void(*xsignalfreeproc)(ptr pData)
信号代码

xrtSignalSupported函数

判断当前平台是否支持指定信号代码。

bool xrtSignalSupported(xsignal Code)

参数

参数方向约束说明
Code输入—信号代码
返回值
返回含义失败时状态
true是支持—
false不是支持—
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

signal_tour · 平台支持查询

	if ( !xrtSignalSupported(XSIGNAL_INT) ||
		!xrtSignalSupported(XSIGNAL_TERM) ||  /* Windows 无 TERM */
		(xrtSignalName(XSIGNAL_INT) == NULL) ||
		(xrtSignalName(XSIGNAL_NONE) == NULL) ||
		!xrtSignalHealthy() ) {

xrtSignalName函数

返回稳定信号名称;未知代码返回 "UNKNOWN"。

cstr xrtSignalName(xsignal Code)

参数

参数方向约束说明
Code输入—信号代码
返回值
返回含义失败时状态
非空稳定名称("INT"、"TERM" 等);未知为 "UNKNOWN"—
错误
  • 无 — 未知代码返回 "UNKNOWN" 且不设置错误

范例已编译验证

signal_tour · 信号名称

		(xrtSignalName(XSIGNAL_INT) == NULL) ||
订阅

xrtSignalOn函数

订阅信号;成功后调用方拥有返回句柄,回调可重复执行。

xsignalwatch* xrtSignalOn(xsignal Code, xsignalproc pProc, ptr pData)

参数

参数方向约束说明
Code输入有效且平台支持信号代码
pProc输入非空信号回调
pData输入任意值回调数据
返回值
返回含义失败时状态
非空监听句柄(引用 1)—
NULL订阅失败xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_CODE(XERR_ARGUMENT) — 信号代码无效
  • xrt.signal / XSIGNAL_ERROR_UNSUPPORTED(XERR_UNSUPPORTED) — 当前平台不支持该信号
  • xrt.signal / XSIGNAL_ERROR_STATE(XERR_STATE) — 调度线程创建失败
  • xrt.signal 域错误(XERR_RANGE) — 监听句柄标识空间耗尽
  • XERR_MEMORY — 句柄分配失败

范例已编译验证

signal · 订阅

	xsignalwatch* pWatch = xrtSignalOn(
		XSIGNAL_INT,
		exampleSignal,
		&Received
	);

xrtSignalOnOwned函数

订阅信号并在句柄最终释放时析构用户数据;失败时数据所有权不转移。

xsignalwatch* xrtSignalOnOwned(xsignal Code, xsignalproc pProc, ptr pData, xsignalfreeproc pFree)

参数

参数方向约束说明
Code输入有效且平台支持信号代码
pProc输入非空信号回调
pData输入任意值回调数据,成功后所有权转移
pFree输入非空数据析构回调
返回值
返回含义失败时状态
非空监听句柄(引用 1)—
NULL订阅失败,数据仍归调用方xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_CODE(XERR_ARGUMENT) — 信号代码无效
  • xrt.signal / XSIGNAL_ERROR_UNSUPPORTED(XERR_UNSUPPORTED) — 当前平台不支持该信号
  • xrt.signal / XSIGNAL_ERROR_STATE(XERR_STATE) — 调度线程创建失败
  • xrt.signal 域错误(XERR_RANGE) — 监听句柄标识空间耗尽
  • XERR_MEMORY — 句柄分配失败

范例已编译验证

signal_tour · 订阅(接管数据)

	pOwned = xrtSignalOnOwned(XSIGNAL_INT, exampleOnCallback,
		NULL, exampleFree);

xrtSignalOnce函数

订阅一次信号;第一次入选调度后先注销,再执行用户回调。

xsignalwatch* xrtSignalOnce(xsignal Code, xsignalproc pProc, ptr pData)

参数

参数方向约束说明
Code输入有效且平台支持信号代码
pProc输入非空信号回调
pData输入任意值回调数据
返回值
返回含义失败时状态
非空一次性监听句柄(引用 1)—
NULL订阅失败xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_CODE(XERR_ARGUMENT) — 信号代码无效
  • xrt.signal / XSIGNAL_ERROR_UNSUPPORTED(XERR_UNSUPPORTED) — 当前平台不支持该信号
  • xrt.signal / XSIGNAL_ERROR_STATE(XERR_STATE) — 调度线程创建失败
  • xrt.signal 域错误(XERR_RANGE) — 监听句柄标识空间耗尽
  • XERR_MEMORY — 句柄分配失败

范例已编译验证

signal_tour · 订阅一次

	pOnce = xrtSignalOnce(XSIGNAL_INT, exampleOnceCallback, NULL);

xrtSignalOnceOwned函数

订阅一次信号并接管用户数据;失败时数据所有权不转移。

xsignalwatch* xrtSignalOnceOwned(xsignal Code, xsignalproc pProc, ptr pData, xsignalfreeproc pFree)

参数

参数方向约束说明
Code输入有效且平台支持信号代码
pProc输入非空信号回调
pData输入任意值回调数据,成功后所有权转移
pFree输入非空数据析构回调
返回值
返回含义失败时状态
非空一次性监听句柄(引用 1)—
NULL订阅失败,数据仍归调用方xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_CODE(XERR_ARGUMENT) — 信号代码无效
  • xrt.signal / XSIGNAL_ERROR_UNSUPPORTED(XERR_UNSUPPORTED) — 当前平台不支持该信号
  • xrt.signal / XSIGNAL_ERROR_STATE(XERR_STATE) — 调度线程创建失败
  • xrt.signal 域错误(XERR_RANGE) — 监听句柄标识空间耗尽
  • XERR_MEMORY — 句柄分配失败

范例已编译验证

signal_tour · 订阅一次(接管数据)

	pOnceOwned = xrtSignalOnceOwned(XSIGNAL_INT,
		exampleOnceCallback, NULL, exampleFree);
句柄生命周期

xrtSignalRef函数

增加监听句柄引用并返回原指针。

xsignalwatch* xrtSignalRef(xsignalwatch* pWatch)

参数

参数方向约束说明
pWatch输入非空目标句柄
返回值
返回含义失败时状态
非空原指针,引用 +1—
NULL参数非法XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或信号代码非法

范例已编译验证

signal_tour · 共享引用

	pRef = xrtSignalRef(pOwned);

xrtSignalOff函数

幂等注销监听;从其他线程调用时,返回前保证该句柄回调已经结束。

bool xrtSignalOff(xsignalwatch* pWatch)

参数

参数方向约束说明
pWatch输入非空目标句柄
返回值
返回含义失败时状态
true已注销(或此前已注销)—
false参数非法或引用失败XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或信号代码非法

范例已编译验证

signal_tour · 幂等注销

	if ( !xrtSignalOff(pOwned) ||
		xrtSignalActive(pOwned) ) {

xrtSignalFree函数

注销监听并释放一个调用方引用;空指针可安全传入。

void xrtSignalFree(xsignalwatch* pWatch)

参数

参数方向约束说明
pWatch输入允许空空 = 空操作
返回值
返回含义失败时状态
无引用 -1,归零时释放并析构数据—
错误
  • 无 — 释放不失败

范例已编译验证

signal · 释放引用

		xrtSignalFree(pWatch);

xrtSignalActive函数

判断监听是否仍会进入新的回调。

bool xrtSignalActive(const xsignalwatch* pWatch)

参数

参数方向约束说明
pWatch输入非空目标句柄
返回值
返回含义失败时状态
true是仍活跃—
false不是仍活跃—
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

signal_tour · 活跃查询

		!xrtSignalActive(pOwned) ||

xrtSignalCode函数

返回监听对应的信号代码;空指针返回 XSIGNAL_NONE。

xsignal xrtSignalCode(const xsignalwatch* pWatch)

参数

参数方向约束说明
pWatch输入非空目标句柄
返回值
返回含义失败时状态
信号代码订阅的代码—
XSIGNAL_NONE参数非法XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或信号代码非法

范例已编译验证

signal_tour · 信号代码查询

		(xrtSignalCode(pOwned) != XSIGNAL_INT) ) {
原生处理方式

xrtSignalIgnore函数

忽略指定信号并注销该代码的全部 XRT 监听。

bool xrtSignalIgnore(xsignal Code)

参数

参数方向约束说明
Code输入有效且平台支持信号代码
返回值
返回含义失败时状态
true已忽略并注销—
false失败xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_CODE(XERR_ARGUMENT) — 信号代码无效
  • xrt.signal / XSIGNAL_ERROR_UNSUPPORTED(XERR_UNSUPPORTED) — 当前平台不支持该信号

范例已编译验证

signal_tour · 忽略信号

	if ( !xrtSignalIgnore(XSIGNAL_INT) ||
		!xrtSignalRestore(XSIGNAL_INT) ||
		!xrtSignalIgnore(XSIGNAL_INT) ||
		!xrtSignalRestoreAll() ) {

xrtSignalRestore函数

注销指定代码的全部监听,并恢复 XRT 接管前的原生处理方式。

bool xrtSignalRestore(xsignal Code)

参数

参数方向约束说明
Code输入有效信号代码
返回值
返回含义失败时状态
true已恢复—
false失败xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_CODE(XERR_ARGUMENT) — 信号代码无效

范例已编译验证

signal_tour · 恢复原生处理

		!xrtSignalRestore(XSIGNAL_INT) ||

xrtSignalRestoreAll函数

注销全部监听并恢复全部由 XRT 接管的原生处理方式。

bool xrtSignalRestoreAll()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
true已全部恢复—
false失败xrt.signal 域错误
错误
  • xrt.signal 域错误 — 恢复过程中平台调用失败

范例已编译验证

signal_tour · 恢复全部

		!xrtSignalRestoreAll() ) {

xrtSignalRaise函数

向当前进程发送原生信号;默认处理方式可能终止进程。

bool xrtSignalRaise(xsignal Code)

参数

参数方向约束说明
Code输入有效且平台可发送信号代码
返回值
返回含义失败时状态
true已发送—
false发送失败xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_CODE(XERR_ARGUMENT) — 信号代码无效
  • xrt.signal / XSIGNAL_ERROR_UNSUPPORTED(XERR_UNSUPPORTED) — 该信号无法在当前平台发送

范例已编译验证

signal · 发送信号

	if ( (pWatch == NULL) || !xrtSignalRaise(XSIGNAL_INT) ) {
计数与关闭

xrtSignalCount函数

返回指定信号的累计接收数;XSIGNAL_NONE 返回全部信号之和。

uint64 xrtSignalCount(xsignal Code)

参数

参数方向约束说明
Code输入有效或 XSIGNAL_NONE信号代码
返回值
返回含义失败时状态
>= 0累计接收数—
错误
  • XERR_ARGUMENT — 指针为空或信号代码非法

范例已编译验证

signal_tour · 累计接收数

		uint64 iBefore = xrtSignalCount(XSIGNAL_INT);

xrtSignalReceived函数

判断指定信号自上次清零后是否至少接收过一次。

bool xrtSignalReceived(xsignal Code)

参数

参数方向约束说明
Code输入有效信号代码
返回值
返回含义失败时状态
true是接收过—
false不是接收过—
错误
  • XERR_ARGUMENT — 指针为空或信号代码非法

范例已编译验证

signal_tour · 接收判断

		if ( !xrtSignalReceived(XSIGNAL_INT) ||
			(xrtSignalCount(XSIGNAL_INT) < 2u) ||
			(iBefore < 2u) ) {

xrtSignalClear函数

清零指定信号的累计数与尚未调度数量;XSIGNAL_NONE 清零全部。

bool xrtSignalClear(xsignal Code)

参数

参数方向约束说明
Code输入有效或 XSIGNAL_NONE信号代码
返回值
返回含义失败时状态
true已清零—
false代码无效XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或信号代码非法

范例已编译验证

signal_tour · 清零计数

		if ( !xrtSignalClear(XSIGNAL_INT) ||
			xrtSignalReceived(XSIGNAL_INT) ||
			(xrtSignalCount(XSIGNAL_INT) != 0u) ) {

xrtSignalHealthy函数

判断调度后端是否健康;故障时重建前必须先调用 xrtSignalShutdown。

bool xrtSignalHealthy()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
true后端是否健康—
false非后端是否健康—
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

signal_tour · 后端健康

		!xrtSignalHealthy() ) {

xrtSignalShutdown函数

停止调度线程、注销全部监听并恢复原生处理方式;回调线程内不可调用。

bool xrtSignalShutdown()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
true已停止并恢复—
false失败xrt.signal 域错误
错误
  • xrt.signal / XSIGNAL_ERROR_STATE(XERR_STATE) — 在信号回调线程内调用(自关闭)

范例已编译验证

signal · 关闭调度

	return xrtSignalShutdown() ? 0 : 3;

常量索引常量

以下常量在本页所属头文件中定义,语义见公共头注释。

常量说明
XSIGNAL_BREAK见头文件注释
XSIGNAL_CLOSE见头文件注释
XSIGNAL_ERROR_CODE见头文件注释
XSIGNAL_ERROR_STATE见头文件注释
XSIGNAL_ERROR_SYSTEM见头文件注释
XSIGNAL_ERROR_UNSUPPORTED见头文件注释
XSIGNAL_HUP见头文件注释
XSIGNAL_INT见头文件注释
XSIGNAL_LOGOFF见头文件注释
XSIGNAL_NONE见头文件注释
XSIGNAL_SHUTDOWN见头文件注释
XSIGNAL_TERM见头文件注释