nanosleep调用后errno被设为ETIMEDOUT,POSIX手册未提及该错误
nanosleep调用后errno被设为ETIMEDOUT的疑问
每次调用nanosleep时,errno都会被设置为ETIMEDOUT(错误码60),这很奇怪——因为POSIX的nanosleep手册里并没有把ETIMEDOUT列为可能出现的错误。
这是个bug,还是我忽略了什么细节?
测试代码
#include <stdio.h> #include <string.h> #include <errno.h> #include <time.h> #define ONE_SC 1000000000 #define ONE_MS 1000000 int main() { struct timespec req = {ONE_MS / ONE_SC, ONE_MS % ONE_SC}; struct timespec rem; printf("errno: %s (%d)\n", strerror(errno), errno); int rv = nanosleep(&req, &rem); printf("errno: %s (%d)\n", strerror(errno), errno); printf("rv: %d\n", rv); return 0; }
代码输出
errno: Undefined error: 0 (0) errno: Operation timed out (60) rv: 0
运行环境
- M1 Pro ARM MacBook
- gcc版本:
gcc-14 (Homebrew GCC 14.2.0_1) 14.2.0
问题解答
核心点在于:只有系统调用返回-1(失败)时,errno的值才是有效的。你的测试里nanosleep返回了0,说明睡眠正常完成,此时errno的数值完全是无意义的——POSIX标准并没有要求成功的系统调用必须重置errno,它可能保留之前的残留值,也可能被底层实现的某些操作意外修改。
根据POSIX规范,nanosleep仅在两种场景下返回错误并设置errno:
EINTR:睡眠过程被信号中断EINVAL:传入的睡眠时间参数无效(比如纳秒部分不在0~999999999范围内)
你看到的ETIMEDOUT,应该是macOS底层实现nanosleep时,内部用到的某些机制(比如更底层的定时器调用)留下的痕迹,但因为最终睡眠成功完成,所以nanosleep返回了0,这个errno值不代表nanosleep本身出错。
这不是bug,完全符合POSIX标准的定义。正确的做法是:只在系统调用返回-1时,才去检查errno,成功调用时直接忽略errno即可。
内容的提问来源于stack exchange,提问作者suuniqo
相关产品推荐
相关产品推荐

