查看 POSIX API 使用说明时,通常会遇到一些 安全性的概念;
本文将举例说明 glibc 2.37 release 中几种 安全概念,避免某些 glibc 库函数 ( 如 malloc ) 的错误姿势。
一. MT-Safe
Multi Thread Safe,很好理解,函数可以 同时在不同线程内执行;
注意,MT-Safe 只是说 “可以同时在不同线程内执行”,不是说函数具有原子性 (atomic) ,或者函数内部使用了某种 内存同步机制;最常见的 MT-Unsafe 例子是
char * strerror (int errnum) //一个线程转换中的 errno 可能被 另一个线程 改变
Preliminary: | MT-Unsafe race:strerror | AS-Unsafe heap i18n | AC-Unsafe mem
可重入 (reentrant ) 是 MT-Safe 的 真子集,可重入函数 同时被两个线程调用时,“由于没有共用数据,或不修改共用数据”,执行结果不会相互影响;
我尝试多线程调用 strerror(errno),但并没有崩溃,没能触发 MT-Unsafe 的场景;
二. AS-Safe
Asynchronous Signal Safe,信号处理过程 可以 调用;
Signal 软中断 打断进程运行后,信号处理 过程中可能破坏 进程的运行环境( 如 errno 或 浮点模式 等),异步信号安全(AS-Safe)函数 会在返回被打断进程的控制流前,恢复运行环境,保障进程安全;最常见的 AS-Unsafe 例子依旧是
char * strerror (int errnum)
Preliminary: | MT-Unsafe race:strerror | AS-Unsafe heap i18n | AC-Unsafe mem
char * strerror_r (int errnum, char *buf, size_t n)
Preliminary: | MT-Safe | AS-Unsafe i18n | AC-Unsafe
其实 绝大多数 函数 都是 AS-Unsafe 的 …
三. AC-Safe
Asynchronous Cancellation Safe,异步撤销 启用后,依旧安全;
POSIX 标准 的众多接口中,只有三个是 AC-Safe 的:pthread_cancel, pthread_setcancelstate 和 pthread_setcanceltype. GNU C 与 POSIX 保持一致;
The routines cannot assume a floating point environment,particularly when asynchronous cancellation is enabled. If the configuration of the floating point environment cannot be performed atomically then it is also possible that the environment encountered is internally inconsistent.
什么是 异步撤销?待日后有空再回头 填坑;