pthread_cond_wait 永远不会带着 EOWNERDEAD 回来

pthread_cond_wait never returning with EOWNERDEAD

我尝试在两个进程之间共享一个互斥体和一个条件变量。一个进程拥有互斥锁并设置条件变量,而另一个进程等待条件变量。 我的理解是当前持有互斥量的进程是“所有者”。当所有者应用程序退出时,该特定互斥锁上的互斥锁应该 return EOWNERDEAD 错误,因为互斥锁是健壮的。到目前为止,这似乎有效。但是如果我等待条件变量,EOWNERDEAD 永远不会 returned 并且调用会无限阻塞。

在“所有者”进程中创建互斥锁和条件变量:

struct InternalEvent {
    pthread_mutex_t lock;
    pthread_cond_t condSet;
    bool set;
    bool manualReset;
};

pthread_mutexattr_t mutexAttr;
pthread_condattr_t conditionAttr;

int filedescriptor = 0;
filedescriptor = ::open(name, O_RDWR | O_CREAT | O_EXCL, 0666);
if (filedescriptor < 0)
    return false;
ftruncate(filedescriptor, sizeof(InternalEvent));
pthread_mutexattr_init(&mutexAttr);
pthread_mutexattr_setrobust(&mutexAttr, PTHREAD_MUTEX_ROBUST);
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_condattr_init(&conditionAttr);
pthread_condattr_setpshared(&conditionAttr, PTHREAD_PROCESS_SHARED);
internalEvent = (InternalEvent*) mmap(NULL, sizeof(InternalEvent), PROT_READ | PROT_WRITE, MAP_SHARED, filedescriptor, 0);
::close(filedescriptor);
pthread_mutex_init(&internalEvent->lock, &mutexAttr);
pthread_cond_init(&internalEvent->condSet, &conditionAttr);
internalEvent->set = false;

在另一个进程中打开互斥锁和条件变量:

filedescriptor = ::open(name, O_RDWR, 0666);
if (filedescriptor < 0)
    return false;
internalEvent = (InternalEvent*) mmap(NULL, sizeof(InternalEvent), PROT_READ | PROT_WRITE, MAP_SHARED, filedescriptor, 0);
::close(filedescriptor);

设置条件变量:

int res = pthread_mutex_lock(&internalEvent->lock);
if(res == EOWNERDEAD) {
    internalEvent->set = false;
    pthread_mutex_consistent(&internalEvent->lock);
}
if(!internalEvent->set)
    pthread_cond_broadcast(&internalEvent->condSet);
internalEvent->set = true;
pthread_mutex_unlock(&internalEvent->lock);

等待条件变量:

int res = pthread_mutex_lock(&internalEvent->lock);

while (!internalEvent->set && res == 0) {
    res = pthread_cond_wait(&internalEvent->condSet, &internalEvent->lock);
}
if(res == 0 && !internalEvent->manualReset) {
    internalEvent->set = false;
}

pthread_mutex_unlock(&internalEvent->lock);
return res == 0;

我的问题是,如何在阻塞的 pthread_cond_wait 调用中检测到“所有者”进程的 termination/crashing/exiting? 我真的不需要恢复互斥锁或条件变量状态。我只想检测终止。

编辑:是否有其他方法可以在一个阻塞调用中等待多个互斥量?然后我可以简单地为每个进程设置一个互斥锁,为条件变量设置一个互斥锁

EOWNERDEADpthread_mutex_lock() 的定义 return 值,而不是 pthread_cond_wait()。这可能是因为 CV 没有与互斥量相同的所有者。无论如何,没有理由期待 return EOWNERDEAD.

的简历等待

此外,专门等待 CV 的线程不会在持续时间内持有关联的互斥量,并且在等待结束之前不会尝试重新获取它。如果 CV 未发出信号,则线程甚至没有任何理由注意到互斥锁所有者已死。*

底线是 POSIX 没有定义稳健的条件变量,就像它定义稳健的互斥锁一样,并且使用带有 CV 的稳健互斥锁不会赋予 CV 稳健性。所以,

how can i detect the termination/crashing/exiting of the "owner" process in the blocking pthread_cond_wait call?

你不能。条件变量没有那个能力。

如果您对一个进程失败导致另一个进程挂起的风险不满意,那么您有多种选择,其中包括:

  • 使用线程而不是进程;
  • 使用 pthread_cond_timedwait() 而不是 pthread_cond_wait(),如果等待超时则中止或尝试恢复;
  • 在等待进程中使用第二个线程来监视其他协作进程的状态,并在必要时采取纠正措施。

*并且那个可能是这里更基本的问题。在持有互斥体时死亡的进程是否是您希望向 CV 发出信号的(唯一)进程?如果是这样,那么您将永远不会在失败案例中看到该信号。