C信号量:sem_wait抛出莫名其妙的错误

我正在研究一个我们必须使用信号量来解决的问题。 我有一个包含两个信号量的数组, sem_wait(&(gsem[me])) ,并且在某些条件下调用sem_wait(&(gsem[me])) ,它应该等到特定进程被唤醒。 但是,由于某种原因,它给了我错误的Bad file descriptor 。 我sem_wait了一下sem_wait ,Open Group规范说这不是sem_wait可能导致的错误。 这让我的整个程序变得疯狂,我不知道为什么会失败。

编辑:违规代码,根据要求。

 120 sem_wait(&mutex); 121 if (inside[opp] > 0 || waiting[opp] > 0) { 122 sem_wait(&screen); 123 printf("%s %u waiting\n", names[me], t); 124 sem_post(&screen); 125 waiting[me]++; 126 sem_post(&mutex); 127 int hg = sem_wait(&(gsem[me])); 128 if (hg < 0) 129 printf("%s\n", strerror(errno)); 130 } 

我应该注意这是一项家庭作业,我们需要使用信号量。 教授称之为“男女皆宜的卫生间”。 男人和女人都可以使用它,但不能同时使用它。 inside[opp]是卫生间异性的人数。 waiting[opp]是等待使用它的异性的数量。 screen是一个信号量,它锁定对stdout访问。 该解决方案基于我们的教科书中使用传递接力棒的读者/作者问题的解决方案。

我还应该注意,我们首先必须在Ada中编写解决方案,然后将其转换为C.我的Ada解决方案有效,我逐字翻译。 我确信这是一些小的语法细节。 最后,我正在研究Snow Leopard,如果有帮助的话。

请记住,Single UNIX Spec可能不一定是您案例中的控制文档。 当然,它应该是,但由于您实际上没有指定平台,可能是您在一个决定遵循不同规则和/或有其他返回代码的环境中。

有几件事需要检查。

1 /你确定 sem_wait返回-1吗? 我见过编码员只是在通话后检查errno ,没有意识到大多数通话都没有在成功时将其设置为零,而是他们只是不管它。 如果在sem_wait调用之前errno设置为EBADF 则可能会出现这种情况。

2 /您是否遵循了创建信号量的所有规则,例如初始化它们?

3 /您指的是有效的信号量吗? 首先,你确定me指数不超出范围吗?

没有看到一些代码,那就是我必须给出的所有建议。


我发现sem_wait ebadf粗略谷歌的sem_wait ebadf就在这里 。 事实certificate,这是在线程环境中使用errno而不包含正确标头的问题。

通过这样做,正在使用全局errno 而不是正确的线程 (这将给出特定于线程的errno )。

这是你的问题,我不知道,但它可能值得研究。


并且更密切地关注这一系列信息,还有其他一些可能性。

4 /您是否使用sem_init初始化信号量。 如果是,请检查其返回值。 消息来自2008年,所以它可能是过时的信息,但OSX可能仍然不支持sem_init ,更喜欢sem_open (见这里 )。 你真的应该检查你所有 sem_函数的返回码,只是为了确定(如果你对它们全部使用sem_init (如果它不受支持)并且只检查一个,你可能会发现它们失败了)。

5 / OSX下的线程errno函数链中存在(是?) 竞争条件 ,其中__error函数在使用errno之前调用另一个库调用pthread_self (在主线程中,或者在其他线程中使用current_thread->errno )。 从技术上讲,这是不允许的,并且有一个小窗口可能会出现问题。