Мьютекс не работает с двумя запущенными процессами

Я программирую на C, используя API win32.
Моя программа начинается с void main , я выполняю какое-то действие, которое создает мьютекс с определенным именем, а затем запускаю для него функцию waitForSingleObject с параметром времени INFINITE.

Затем я запускаю EXE-процесс с помощью функции createProcess.
Процесс EXE имеет аналогичный код, который теперь выполняет createMutex с тем же именем, что и раньше с родительским процессом.

Насколько я понимаю, я должен получить дескриптор того же мьютекса, который я создал в родительской программе, потому что он имеет то же имя. Поэтому после этого EXE-код также снова выполняет функцию WaitForSingleObject для дескриптора мьютекса с теми же параметрами.

Я ожидал, что это остановится и подождет сейчас, но это продолжалось, поскольку это было каким-то образом сигнализировано, но я никак не мог подать сигнал где-либо на этом этапе.
Я попытался заменить параметр INFINITE на 0 и посмотреть, получу ли я WAIT_TIMEOUT, но и это не сработало.
Почему мой мьютекс не работает?

Спасибо

добавлен соответствующий код: (я пытался поместить только то, что имеет значение) * обратите внимание, что EXE-файл Process1 содержит код, который делает openfileInDirectory с тем же именем файла, что и в void main и для записи. ** Мой мьютекс называется writeMutex. FileSystemMutex — еще один, который не имеет ничего общего с моей текущей проблемой.

// Global variables definition from library header
void* viewVec;
HANDLE fileHandle;
int directoryLastBlockIndex;
FilesInProcessUse processFiles;          
HANDLE fileSystemMutex;
HANDLE filesAccessSemaphore;

void main()
{         

    FileDescriptor* fd, *fd2;
    int message,message2,message3;
    int processId = GetCurrentProcessId();
    char* input= NULL;

    /* print out our process ID */
    printf("Process %d reporting for duty\n",processId);


    fileSystemMutex = CreateMutex(NULL,FALSE,FILE_SYSTEM_MUTEX_NAME);
    printf("Process %d: After creating fileSystem mutex\n",processId);
    filesAccessSemaphore = CreateSemaphore(NULL,MAX_ACCESSORS_FOR_ALL_FILES,MAX_ACCESSORS_FOR_ALL_FILES,FILE_SYSTEM_SEMAPHORE_NAME);
    printf("Process %d: After creating filesAccessSemaphore\n",processId);

    initfs("C",NUM_OF_BLOCKS_IN_DISK,NUM_OF_BLOCKS_IN_DISK);

    viewVec = attachfs("C"); // Saving the address of the vector in global pointer.  

    if(viewVec!=NULL)
    {
        printf("Process %d: After AttachFS which succeded\n",processId);
        fd = (FileDescriptor*) createFileInDirectory("FileX",2,&message);
        if (fd!=NULL)
        {
            printf("Process %d:successfuly created the file: FileX in Drive C\n",processId);
        }
        else
        {
            printErrMessage(message);
        }
    }
    else
    {
        printf("Process %d: After AttachFS, which failed\n",processId);
    }

    fd = (FileDescriptor*) openFileInDirectory("FileX",READ_PERMISSION,&message);
    if(fd!=NULL)
    {
        printf("Process %d: opened FileXfile for read succefully",processId);
    }
    else
    {
        printf("Process %d:",processId);
        printErrMessage(message);
    }
    closeFileInDirectory(fd);
    fd = (FileDescriptor*) openFileInDirectory("FileX",WRITE_PERMISSION,&message);
    if(fd!=NULL)
    {
        printf("Process %d: opened FileXfile for write succefully",processId);
    }
    else
    {
        printf("Process %d:",processId);
        printErrMessage(message);
    }

    fd2 = (FileDescriptor*) openFileInDirectory("FileX",WRITE_PERMISSION,&message);
    if(fd!=NULL)
    {
        printf("Process %d: opened FileX file for write succefully",processId);
    }
    else
    {
        printf("Process %d:",processId);
        printErrMessage(message);
    }
}
}


void* openFileInDirectory(char* fileName, int ReadWriteFlag, int* out_ErrMessage)
{

    SystemInfoSection* sysInfo = readSystemInformationFromBeginingOfVector((char*)viewVec);
    DirectoryEntry* fileEntryInDirOffset;
    FileDescriptor* openfileDescriptor = NULL;
    int fileIndexInOpenFiles = 0;
    int writeRV;

    //Mark that another file is being processed 
    WaitForSingleObject(filesAccessSemaphore,INFINITE);


    //Check if the file exists else return error
    if(isFileAlreadyExisting(fileName, sysInfo->directoryStartBlockIndex, &fileEntryInDirOffset))
    {
        fileIndexInOpenFiles = getFileIndexInOpenFileDirectory(fileName);
        processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore = CreateSemaphore(NULL,MAX_FILE_ACCESSORS,MAX_FILE_ACCESSORS,fileName);
        WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore,INFINITE);
        if (ReadWriteFlag == WRITE_PERMISSION)
        {
            char writeMutexName[15];
            strcpy(writeMutexName, WRITE_MUTEX_PREFIX);
            strcat(writeMutexName, fileName);
            processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex = CreateMutex(NULL,FALSE,writeMutexName);

            WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex,INFINITE);

            //writeRV = WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex,MAX_WAIT_TIMEOUT_IN_FS);
            //if(writeRV == WAIT_TIMEOUT)
            //{
            //  ReleaseSemaphore(processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore,1,NULL);
            //  //return error indicating that another process is already writing to the file AND RETURN FROM THE FUNCTION
            //  *out_ErrMessage = ERR_FILE_IS_ALREADY_OPEN_TO_A_WRITE_BY_SOME_PROCESS;
            //  return openfileDescriptor;

            //}
        }

        processFiles.FDInProcessUseVector[fileIndexInOpenFiles].fileDirectoryEntry = fileEntryInDirOffset;
        processFiles.FDInProcessUseVector[fileIndexInOpenFiles].readWriteFlag = ReadWriteFlag;
        openfileDescriptor = &(processFiles.FDInProcessUseVector[fileIndexInOpenFiles]);
        processFiles.numOfFilesInUse++;


    }

    else
    {
        openfileDescriptor = NULL;
        *out_ErrMessage = ERR_FILE_NOT_FOUND;
    }
    free(sysInfo);

    return openfileDescriptor;
}

person JavaSa    schedule 06.02.2012    source источник
comment
@ Кейт Николас: спасибо за добавленный код комментария, я мог бы добавить гораздо больше, но я думаю, что этого достаточно.   -  person JavaSa    schedule 07.02.2012
comment
Вы получаете ERROR_ALREADY_EXISTS, как ожидалось?   -  person Ben Voigt    schedule 07.02.2012
comment
Судя по вашему описанию, первый процесс никогда не будет ждать, так как ждать нечего...   -  person Deanna    schedule 07.02.2012
comment
В первый раз, когда я делаю createMutex, я получаю FILE_NOT_FOUND, во второй раз я получаю ACCESS_DENIED, но это когда я пытаюсь сделать дважды открыть для записи из одного и того же процесса, потому что я не могу отлаживать EXE-файл, если я не подложу туда какие-то prinfs   -  person JavaSa    schedule 07.02.2012
comment
Вы говорите, что используете мьютекс, но код, который вы разместили, использует семафор (я думаю, нет мьютекса с именем writeMutex, и вы сказали нам игнорировать fileSystemMutex). Причина, по которой ваше ожидание на семафоре успешно, заключается в том, что он доступен. Вы установили для второго параметра CreateSemaphore значение MAX_ACCESSORS_FOR_ALL_FILES. Вы должны сократить свой код до минимума, который компилируется и демонстрирует проблему.   -  person tinman    schedule 07.02.2012
comment
Я также использую семафоры, но это не проблема, проблема заключается в определенном мьютексе, который используется в функции openFileInDirectory, у вас есть это как: processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex, а вызов ожидания: WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex,INFINITE);   -  person JavaSa    schedule 07.02.2012
comment
@Deanna: Не могли бы вы объяснить, почему?   -  person JavaSa    schedule 07.02.2012
comment
@JavaSa: Поскольку вы предоставили свой код, я обновил свой ответ. Дайте мне знать, если это помогло вам.   -  person LihO    schedule 07.02.2012
comment
Из вашего описания: я выполняю некоторые действия, которые создают мьютекс с определенным именем, а затем запускают на нем функцию waitForSingleObject с параметром времени INFINITE. Если он создал его первым, то он уже владеет им, и ожидание завершится немедленно. Ожидание происходит только тогда, когда оно уже есть у кого-то другого.   -  person Deanna    schedule 07.02.2012
comment
@Deanna: Это неправда, потому что в показанном коде для параметра bInitialOwner установлено значение FALSE.   -  person Ben Voigt    schedule 07.02.2012
comment
В этом случае он никому не принадлежит, и ожидание все равно завершится. он будет блокироваться только в том случае, если что-то еще активно удерживает мьютекс в этот момент времени, чего я не могу сказать по их информации и коду.   -  person Deanna    schedule 07.02.2012
comment
@Deanna: это не обязательно правда. Если вызывается CreateMutex, а другой процесс вызывает CreateMutex сразу после него, другой процесс может получить дескриптор этого мьютекса, а также права собственности, вызвав WaitForSingleObject до того, как первый процесс вызовет WaitForSingleObject.   -  person LihO    schedule 07.02.2012


Ответы (1)


Вы можете использовать CreateMutex названный глобальный мьютекс.

Логика использования глобального мьютекса обычно следующая:

  1. Вы пытаетесь создать мьютекс с помощью CreateMutex. Обратите внимание, что "Если мьютекс является именованным мьютексом и объект существовал до вызова этой функции, возвращаемое значение является дескриптором существующего объекта".
  2. Вы блокируете (получаете право собственности) с помощью функции WaitForSingleObject< /а>
  3. Вы разблокируете (освободите право собственности) с помощью функции ReleaseMutex< /а>
  4. Вы CloseHandle возвращены Функция CreateMutex.

Вот хороший пример на C: Использование объектов Mutex< /а>

В вашем коде есть несколько проблем:

  1. Вы не освобождаете права собственности на writeMutex, что, вероятно, является основной причиной, по которой этот код не работает.
  2. Вы не проверяете возвращаемое значение одного вызова. Единственное возвращаемое значение, которое вы проверяете, — это значение, возвращаемое вашей функцией. Ознакомьтесь с документацией по этим функциям, чтобы правильно обрабатывать возможные состояния ошибок.
  3. Вы не возвращаете CloseHandle CreateMutex. Ни дескриптор fileSystemMutex, ни дескриптор writeMutex.
  4. Вы создаете fileSystemMutex, но потом никогда его не используете. Этот мьютекс не имеет там никакого смысла.
person LihO    schedule 06.02.2012
comment
Как обрабатывается мой мьютекс, если я не включаю префиксы \Global или \Local к имени моего мьютекса? - person JavaSa; 07.02.2012
comment
Существует состояние гонки, о котором вам следует знать: другой процесс может создать мьютекс после сбоя OpenMutex, но до вашего вызова CreateMutex. Тогда ваш вызов CreateMutex фактически подключится к существующему мьютексу. Не проблема сама по себе, но это, похоже, сводит на нет полезность проверки OpenMutex. - person Ben Voigt; 07.02.2012
comment
обычно вам не нужно использовать \Global. Глобальное означает, что пространство имен работает между сеансами и требует, чтобы создатель взаимного текста имел привилегию, обычно принадлежащую только системе или администраторам. - person John; 07.02.2012
comment
Я до сих пор не понимаю, в чем основная проблема с моим конкретным мьютексом в моем коде. - person JavaSa; 07.02.2012
comment
Я не вижу никакой расы :) если вы можете указать это снова, я буду благодарен - person JavaSa; 07.02.2012
comment
@BenVoigt: Я не осознавал такой возможный сценарий, спасибо, что открыли мне глаза! ;) - person LihO; 07.02.2012
comment
@Джон: Спасибо за объяснение. Я тоже этого не знал. Я обновил свой ответ. - person LihO; 07.02.2012