【发布时间】:2021-12-28 22:01:53
【问题描述】:
嘿!
我已经在这里查找了类似的问题,但没有得出最终的解决方案。
在我的应用程序中,我有两个同时运行的进程需要通过共享内存进行同步。目前我正在使用 pthread_mutex_t 和 pthread_cond_t 用于该目的,它们被放入共享内存中。
这工作正常,直到进程 A 在等待条件时崩溃。如果进程 A 重新启动,则会发生死锁(?),其中进程 A 等待条件,而进程 B 在调用 pthread_cond_broadcast 时无限期卡住。
我读到这可能是由于互斥体处于不一致状态,但实际上它似乎从未出现在我的程序中。 如果您能告诉我我是否误解了某些东西,或者是否有解决此问题的替代方法,或者根本不可能保护这种崩溃情况,我将不胜感激。
struct Poller
{
private:
std::atomic<bool> waiting;
pthread_mutex_t mtx;
pthread_cond_t cnd;
auto lockMutex() -> void
{
// Recover Mutex if any process locking it died unexpectedly
LOG_DEBUG(info, "AdaptivePoller", "Locking mutex...");
if(pthread_mutex_lock(&mtx) == EOWNERDEAD) {
LOG_DEBUG(info, "AdaptivePoller", "Mutex in inconsistent state.");
if(pthread_mutex_consistent(&mtx) != 0) {
throw std::runtime_error("Mutex could not be brought back into consistent state.");
}
}
}
public:
Poller()
{
waiting = false;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&mtx, &attr);
pthread_mutexattr_destroy(&attr);
pthread_condattr_t attrcond;
pthread_condattr_init(&attrcond);
pthread_condattr_setpshared(&attrcond, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&cnd, &attrcond);
pthread_condattr_destroy(&attrcond);
}
auto wait() -> void
{
lockMutex();
waiting = true;
LOG_DEBUG(info, "AdaptivePoller", "Start waiting...");
while(waiting) {
pthread_cond_wait(&cnd, &mtx);
}
pthread_mutex_unlock(&mtx);
}
auto notify() -> void
{
lockMutex();
waiting = false;
LOG_DEBUG(info, "AdaptivePoller", "Notifying...");
pthread_cond_broadcast(&cnd);
pthread_mutex_unlock(&mtx);
}
};
【问题讨论】:
-
你从
pthread_mutex_lock中检查EOWNERDEAD,但不是从pthread_cond_wait,它在返回之前也获得了锁,可以返回EOWNERDEAD。如果有帮助,请告诉我(在评论中使用@ikegami)。 -
POSIX 不为其条件变量提供稳健性选项。众所周知,实现会有所不同,但在最近的 glibc 中,例如,如果进程在进程共享 CV 上的
pthread_cond_wait()中被阻塞时死亡,则该 CV 的状态不可恢复。 -
@JohnBollinger 感谢您提供的信息!你知道/你能推荐另一种方法来实现类似的同步行为,比如在我的应用程序中,并且能够正确处理这种极端情况吗?
-
Related stackoverflow.com/questions/69650814/… 也许可以拉伸成副本。
-
@Varrick,我看到的同步行为是一个或多个线程可以自己阻塞,直到稍后另一个线程解除阻塞所有等待的线程。这是对您想要实现的目标的准确和充分的描述吗?
标签: c++ pthreads ipc shared-memory