Вот некоторые предположения о том, что может происходить.Несколько предостережений по этому анализу:
- это основано на предположении, что вы используете пакет pthreads Win32 из http://sourceware.org/pthreads-win32/
- , это основано только на довольно кратком исследованииисточника pthreads на этом сайте и информации в вопросе и комментариях здесь - у меня не было возможности фактически попытаться запустить / отладить любой код.
Когда вызывается pthread_mutex_unlock()
, он уменьшает счетчик блокировок, и если этот счетчик блокировок падает до нуля, API-интерфейс Win32 SetEvent()
вызывается для связанного объекта события, чтобы разрешить разблокировку любых потоков, ожидающих мьютекс.Довольно стандартные вещи.
Вот где приходят предположения. Допустим, что SetEvent()
был вызван для разблокирования потока (ов), ожидающих мьютекс, и он сигнализирует о событии, связанном с указанным им дескриптором (как это должно).Однако, прежде чем функция SetEvent()
сделает что-то еще, другой поток начинает работать и закрывает дескриптор объекта события, с которым был вызван тот конкретный SetEvent()
(вызывая pthread_mutex_destroy()
).
Теперь SetEvent()
выполняемый вызов имеет значение дескриптора, которое больше не является допустимым.Я не могу вспомнить конкретную причину, по которой SetEvent()
будет что-то делать с этим дескриптором после того, как он сообщит о событии, но, возможно, это так (я мог бы также представить, что кто-то дает разумный аргумент, что SetEvent()
должен ожидатьДескриптор объекта события остается действительным в течение всего времени вызова API).
Если это то, что происходит с вами (и это большой , если), я не уверен, что есть простойисправить.Я думаю, что в библиотеке pthreads должны быть внесены изменения, чтобы она дублировала дескриптор события перед вызовом SetEvent()
, а затем закрыла этот дубликат при возврате вызова SetEvent()
.Таким образом, дескриптор останется действительным, даже если «основной» дескриптор будет закрыт другим потоком.Я предполагаю, что это должно было бы сделать это во многих местах.Это можно реализовать, заменив затронутые вызовы Win32 API вызовами функций-оболочек, которые выполняют последовательность «дублирование дескриптора / вызов API / закрытие дубликата».
Возможно, вы попытаетесь внести это изменение без необходимостидля SetEvent()
звоните в pthread_mutex_unlock()
и посмотрите, решит ли (или хотя бы улучшит) вашу конкретную проблему.Если это так, вы можете связаться с сопровождающим библиотеки, чтобы узнать, можно ли как-то организовать более полное исправление (будьте готовы - вас могут попросить выполнить значительную часть работы).
ИзЛюбопытно, что при отладке состояния потока, который зависает в pthread_mutex_unlock()
/ SetEvent()
, есть ли у вас какая-либо информация о том, что именно происходит?Чего ждет * 1037?(отладчик cdb, входящий в пакет средств отладки для Windows, может дать вам больше информации об этом, чем отладчик Visual Studio).
Также обратите внимание на следующий комментарий в источнике для pthread_mutex_destroy()
, который выглядитсвязаны (но отличаются) от вашей конкретной проблемы:
/*
* FIXME!!!
* The mutex isn't held by another thread but we could still
* be too late invalidating the mutex below since another thread
* may already have entered mutex_lock and the check for a valid
* *mutex != NULL.
*
* Note that this would be an unusual situation because it is not
* common that mutexes are destroyed while they are still in
* use by other threads.
*/