You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS下POSIX信号量报错‘Semaphore closing failed: Bad file descriptor’排查

错误原因分析
  • 同名命名信号量的冲突:POSIX命名信号量是系统全局的,同一个名称在系统中只能对应一个实例。你用"/my_semaphore"重复三次调用sem_open,第一次创建成功后,后续两次实际是打开同一个已存在的信号量,而非创建新的。当你尝试关闭这三个指向同一信号量的句柄时,若其中某次关闭已经释放了文件描述符,后续重复关闭就会触发「Bad file descriptor」错误。
  • macOS信号量接口限制:macOS对无名信号量的sem_init/sem_destroy支持有限,改用命名信号量的sem_open/sem_close是正确方向,但参数使用不符合规范。
信号量打开参数的正确用法
  • 名称必须唯一:每个信号量要使用不同的系统级名称,比如"/my_sem_1"、"/my_sem_2"、"/my_sem_3",避免冲突。
  • sem_open参数规范:
    • 名称必须以/开头(POSIX标准强制要求,macOS严格执行)。
    • 创建新信号量时,用O_CREAT | O_EXCL组合标志,确保信号量不存在时才创建,避免意外复用旧实例;仅打开已有信号量时用O_RDWR。
    • 权限位设为0644这类合理值,保证进程有访问权限。
    • 初始值根据业务需求设置(比如同步信号量设1,资源信号量设对应资源数)。
修复代码示例

正确的初始化与销毁函数:

#include <semaphore.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

sem_t* init_semaphore(const char* name, unsigned int value) {
    sem_t* sem = sem_open(name, O_CREAT | O_EXCL, 0644, value);
    if (sem == SEM_FAILED) {
        perror("Semaphore creation failed");
        return NULL;
    }
    return sem;
}

void cleanup_semaphore(sem_t* sem, const char* name) {
    if (sem != SEM_FAILED) {
        if (sem_close(sem) == -1) {
            perror("Semaphore closing failed");
        }
        // 必须unlink删除系统中的信号量条目,否则下次启动会残留
        if (sem_unlink(name) == -1) {
            perror("Semaphore unlinking failed");
        }
    }
}

调用时使用不同名称:

sem_t* sem1 = init_semaphore("/my_sem_1", 1);
sem_t* sem2 = init_semaphore("/my_sem_2", 0);
sem_t* sem3 = init_semaphore("/my_sem_3", 1);

// 业务逻辑...

cleanup_semaphore(sem1, "/my_sem_1");
cleanup_semaphore(sem2, "/my_sem_2");
cleanup_semaphore(sem3, "/my_sem_3");

内容的提问来源于stack exchange,提问作者AndreasKaram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:33:13