在信号处理程序中调用sem_post()是否属于未定义行为?
在信号处理程序中调用sem_post()是否依赖未定义行为?
咱们来仔细拆解这个问题:
首先看给出的代码片段:
/* * excerpted from the 2017-09-15 Linux man page for sem_wait(3) */ ... sem_t sem; ... static void handler(int sig) { write(STDOUT_FILENO, "sem_post() from handler\n", 24); if (sem_post(&sem) == -1) { write(STDERR_FILENO, "sem_post() failed\n", 18); _exit(EXIT_FAILURE); } }
这里的信号量sem是静态存储期对象,而你提到了POSIX.1-2008的一条规定:
若信号处理程序引用除errno外的静态存储期对象,且并非对volatile sig_atomic_t类型对象赋值,则行为未定义...
乍一看好像直接引用静态的sem会违反这条规则,但其实这里有个关键细节要区分:
- 首先,
sem_post()是POSIX明确标记的异步信号安全函数,这类函数的设计目标就是支持在信号处理程序中调用,内部已经处理了并发/信号上下文的安全问题。 - 上述POSIX规则的核心是限制用户代码直接对静态存储期对象进行非原子的读写操作——比如你直接去修改一个普通静态变量的值,这种操作会因为信号的异步特性导致数据竞争,从而触发未定义行为。但通过异步信号安全的函数来操作静态对象,并不属于规则中禁止的“引用”行为。
sem_post()会以原子方式操作信号量的内部状态,它对sem对象的访问是安全且符合标准的。所以这种在信号处理程序中调用sem_post(&sem)的用法,并不依赖未定义行为,是完全合法的。
内容的提问来源于stack exchange,提问作者pilcrow
相关产品推荐
相关产品推荐

