CreateMutex (), кажется, получает мьютекс, даже когда ERROR_ALREADY_EXISTS - PullRequest
0 голосов
/ 11 января 2019

Я использую CreateMutex для создания глобального мьютекса, чтобы предотвратить запуск нескольких экземпляров приложения. При первом запуске CreateMutex возвращает дескриптор, а GetLastError возвращает ERROR_SUCCESS, мьютекс создается и получается. При втором запуске CreateMutex также возвращает некоторый дескриптор, но GetLastError возвращает ERROR_ALREADY_EXISTS. В этом случае я показываю пользователю сообщение и выхожу из программы.

Проблема: когда этот второй экземпляр ожидает закрытия, а затем я закрываю первый экземпляр, а затем пытаюсь запустить другой новый экземпляр, он не сможет получить мьютекс. Он также получит ERROR_ALREADY_EXISTS, но почему? Первый экземпляр уже закрыт, поэтому мьютекс должен быть освобожден системой. Это означает, что второй экземпляр каким-то образом мешает третьему получить мьютекс!

Проблема решается добавлением ReleaseMutex и CloseHandle после неудачной попытки получить мьютекс. Но почему это имеет значение?

#include <Windows.h>
#include <cstdio>

int main()
{
    printf("Starting\n");

    HANDLE returnedHandle = CreateMutex(NULL, TRUE, TEXT("Global\\my_unique_name"));
    DWORD lastError = GetLastError();

    printf("CreateMutex: %i, GetLastError: %i\n", returnedHandle, lastError);

    if (lastError != ERROR_SUCCESS)
    {
        printf("Mutex already in use! Cannot run.\n");

        //why is this needed?
        //
        //if (returnedHandle != NULL)
        //{
        //  ReleaseMutex(returnedHandle);
        //  CloseHandle(returnedHandle);
        //}
    }
    else
    {
        printf("This is first instance.\n");
        //RunRestOfProgram();
    }

    printf("Press Enter to close.");
    getchar();
}

Вывод первого экземпляра:

CreateMutex: 200, GetLastError: 0
This is first instance.
Press Enter to close.

Выход второго экземпляра:

CreateMutex: 204, GetLastError: 183
Mutex already in use! Cannot run.
Press Enter to close.

Вывод третьего экземпляра после закрытия первого экземпляра, но не закрытия второго экземпляра:

CreateMutex: 212, GetLastError: 183
Mutex already in use! Cannot run.
Press Enter to close.

1 Ответ

0 голосов
/ 11 января 2019

Первый CreateMutex вызов создает мьютекс. Когда вы снова вызываете CreateMutex, и он уже существует, функция открывается и возвращает дескриптор мьютекса. Когда вы закрываете первый процесс, мьютекс все еще существует, потому что у второго процесса есть дескриптор.

ReleaseMutex в этом случае не требуется, только вызов CloseHandle.

Когда вы вызываете CloseHandle, больше нет процессов, удерживающих дескриптор мьютекса, поэтому система уничтожает его.

...