Здравствуйте, CyberDemon, Вы писали:
CD>... CD>Я что-то где-то не так сделал или что?
Проверка ошибок везде есть? Т.е. что CreateMutex и OpenMutex возвращают не NULL
Проверяется ли после успешного CreateMutex, что это создание нового мьютекса, а
не открытие уже существующего (т.е. что GetLastError() != ERROR_ALREADY_EXISTS)?
Если это открытие, то ReleaseMutex делать нельзя, т.к. не мы его захватили.
Т.е. более точная последовательность действий примерно такая:
Вызываем CreateMutex с флагом bInitialOwner = TRUE.
Если успех, вызываем GetLastError(). Если там ERROR_ALREADY_EXISTS, значит,
мьютекс уже существует, надо делать WaitForSingleObject и ждать, пока
он освободится. И только когда освободится, можно выполнять свою работу и
потом освобождать его через ReleaseMutex.
Второе приложение делает примерно то же самое, только у него OpenMutex
вместо CreateMutex (хотя на самом деле CreateMutex можно и там, и там).
Все работает отлично в Windows 10, 7 (у себя проверял). Но вдруг начали появляться юзеры с проблемами в 7.
Выяснил, что во втором процессе Wait вешается навечно. То есть, mutex открыт, ошибок нет, но залочить его не можем.
Костыль выглядит так:
// if Windows 7
mutex = CreateMutex(NULL, FALSE, name);
Здравствуйте, okman, Вы писали:
O>Здравствуйте, CyberDemon, Вы писали:
CD>>... CD>>Я что-то где-то не так сделал или что?
O>Проверка ошибок везде есть? Т.е. что CreateMutex и OpenMutex возвращают не NULL
Да, конечно, это все проверяется. И перед Wait на NULL тоже проверка есть.
O>Проверяется ли после успешного CreateMutex, что это создание нового мьютекса, а O>не открытие уже существующего (т.е. что GetLastError() != ERROR_ALREADY_EXISTS)?
O>Если это открытие, то ReleaseMutex делать нельзя, т.к. не мы его захватили. O>Т.е. более точная последовательность действий примерно такая:
Основное приложение (которое админ) первое создает mutex, его в системе быть не может.
O>Вызываем CreateMutex с флагом bInitialOwner = TRUE. O>Если успех, вызываем GetLastError(). Если там ERROR_ALREADY_EXISTS, значит, O>мьютекс уже существует, надо делать WaitForSingleObject и ждать, пока O>он освободится. И только когда освободится, можно выполнять свою работу и O>потом освобождать его через ReleaseMutex.
Еще раз перечитал свое первое сообщение и понял, что, возможно, я немного криво написал про костыль.
CreateMutex без InitialOwner = FALSE я делаю во втором процессе. А первый все так же с TRUE.
То есть, CreateMutex вместо OpenMutex — это и есть костыль.
Здравствуйте, IID, Вы писали:
IID>основное приложение могло не запуститься или сдохнуть (или закрыть мьютекс)
Если не запустится основное, не запустится и "клиент". Специфика.
Закрыть раньше времени оно его не может. Это точно.
Сдохнуть может, но это уже другой вопрос и эта ситуация, очевидно, легко наблюдается.
Здравствуйте, CyberDemon, Вы писали:
CD>Я что-то где-то не так сделал или что?
Можно попросить пользователя сдампать оба процесса.
(Это может таск менеджер, который по Ctrl+Shift+ESC, или Ctr+Alt+Del -> Task Manager. Если включён UAC, то чтобы добраться до адмиских процессов, нажать там Show All Processes)
Затем оба дампа открыть в WinDbg и вызвать
!handle 0 0xf Mutant
Напишет все хендлы мьютексов, с подробной информацией, можно будет проверить:
* Тот же самый ли мьютекс в разных процессах
* Занят ли мьютекс или свободен
* Если мьютекс занят, то кем (вдруг Mutant Owner — третий процесс, например, другая копия пользовательского процесса)
Из тех же дампов по !analyze -v
* По колл стеку понять, действительно ли пользовательский процесс ждёт
* По колл стеку понять, действительно ли сервис прошел свой ReleaseMutex