Невозможно получить блокировку на QMutex
Приложение, над которым я сейчас работаю, является многопоточным, с несколькими ресурсами, которые распределяются между потоками. Я использую QMutexes для защиты общих ресурсов, хотя на практике конфликт между разными потоками, пытающимися заблокировать один и тот же мьютекс, должен быть очень редко.
Тем не менее, я нахожу с огорчительной частотой, что мое приложение останавливается. Когда я прекращаю выполнение и проверяю, что происходит, я обнаруживаю, что поток остановлен, потому что он не может получить блокировку для требуемого мьютекса.
Я проверил, что мьютексы всегда блокируются и разблокируются из одного и того же потока - фактически, почти всегда в пределах одного блока фигурных скобок - и в моем последнем раунде устранения неполадок я заменил все мои голые QMutexes на определенные объекты 'nMutex' следующее:
class nMutex : public QMutex
{
public:
nMutex() : QMutex(),
locks(0),
{}
void lock(const char * callingFilename, int callingLineNo)
{
// QMutex::lock(); // Frequently hangs, so tried the following instead...
if (!tryLock(1000))
{
printf("Cannot obtain mutex at line %d of %s; locks = %d",
callingLineNo, callingFilename, locks);
}
else
{
if (isRecursive())
++locks;
else
locks = 1;
}
}
bool tryLock(int timeout = 0) // Hides rather than overrides QMutex's tryLock,
// which is not virtual
{
bool result = QMutex::tryLock(timeout);
if (result)
{
if (isRecursive())
++locks;
else
locks = 1;
}
return result;
}
bool isLocked() const { return (locks > 0); }
int lockDepth() const { return locks; }
void unlock()
{
if (!locks) return;
QMutex::unlock();
if (isRecursive())
--locks;
else
locks = 0;
}
private:
int locks;
};
... и заменил все мои вызовы mutex.lock() на
mutex.lock(__FILE__, __LINE__).
Я обнаружил, что это довольно часто терпит неудачу, и когда это происходит, он всегда сообщает "locks = 0" - другими словами, ни у одного другого потока уже нет мьютекса, и все же поток, пытающийся его получить, не может его получить., Сбои происходят, по-видимому, случайно, независимо от того, где в моем коде сделан вызов mutex.lock().
В настоящее время я вижу две возможности:
(1) Я очень глуп, и не вижу, что что-то не так с вышеуказанным подходом, или
(2) В QMutex есть ошибка. Это кажется маловероятным, поскольку я не видел отчетов, и я пробовал это по крайней мере в трех версиях Qt 5.3 и 5.4 (включая самую последнюю версию 5.4.1).
Есть ли способ проверить, какая из этих двух возможностей наиболее вероятна? Например, в случаях, когда мьютекс не может быть получен, есть ли способ выяснить, почему это так?