我嘗試在兩個行程之間共享一個互斥鎖和一個條件變數。一個行程擁有互斥鎖并設定條件變數,而另一個行程等待條件變數。我的理解是當前持有互斥鎖的行程是“所有者”。當所有者應用程式退出時,該特定互斥鎖上的互斥鎖應該回傳 EOWNERDEAD 錯誤,因為互斥鎖是健壯的。到目前為止,這似乎奏效了。但是,如果我等待條件變數,則永遠不會回傳 EOWNERDEAD 并且呼叫只是無限阻塞。
在“所有者”行程中創建互斥鎖和條件變數:
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 呼叫中檢測到“所有者”行程的終止/崩潰/退出?我真的不需要恢復互斥鎖或條件變數狀態。我只想檢測終止。
編輯:是否有其他方法可以在一個阻塞呼叫中等待多個互斥鎖?然后我可以簡單地為每個行程設定一個互斥鎖,并為條件變數設定一個互斥鎖
uj5u.com熱心網友回復:
EOWNERDEAD是定義的回傳值pthread_mutex_lock(),而不是pthread_cond_wait()。這可能是因為 CV 沒有與互斥鎖相同的所有者。在任何情況下,都沒有理由期望等待 CV 回傳EOWNERDEAD。
此外,在 CV 上等待的執行緒在持續時間內不會持有關聯的互斥體,并且在等待結束之前不會嘗試重新獲取它。如果 CV 沒有發出信號,那么執行緒甚至沒有任何理由注意到互斥鎖所有者已死。*
底線是 POSIX 沒有定義穩健的條件變數,就像它定義穩健的互斥鎖一樣,并且使用帶有 CV 的穩健互斥鎖不會賦予 CV 穩健性。所以,
如何在阻塞 pthread_cond_wait 呼叫中檢測“所有者”行程的終止/崩潰/退出?
你不能。條件變數沒有這種能力。
如果您對一個行程失敗導致另一個行程掛起的風險不滿意,那么您有多種選擇,其中包括:
- 使用執行緒而不是行程;
- 如果等待超時,請使用
pthread_cond_timedwait()代替pthread_cond_wait(),并中止或嘗試恢復; - 在等待行程中使用第二個執行緒來監視其他協作行程的狀態,并在必要時采取糾正措施。
*這可能是一個更根本的問題。持有互斥鎖時終止的行程是(唯一)您希望向 CV 發出信號的行程嗎?如果是這樣,那么您將永遠不會在失敗案例中看到該信號。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/461194.html
