WaitForSingleObject, вызванный на семафоре, завершается ошибкой с последней ошибкой 183 (ERROR_ALREADY_EXISTS)

#c #multithreading #winapi #semaphore

#c #многопоточность #winapi #семафор

Вопрос:

Я пытаюсь написать класс BlockingQueue для задач в стиле производитель-потребитель. Я использую WinAPI, но у меня проблема WaitForSingleObject . Когда я вызываю его в семафоре со значением 0, вместо того, чтобы засыпать, он возвращает -1 (WAIT_FAILED) и GetLastError() выдает 183 (ERROR_ALREADY_EXISTS). Это не имеет для меня никакого смысла, поэтому я думаю, что я, должно быть, делаю что-то ужасно неправильное. Метод, в котором появляется проблема, выглядит следующим образом:

 template<typename elem_t>
elem_t BlockingQueue<elem_t>::pop() {

    WaitForSingleObject(_used_sem, INFINITE);
    WaitForSingleObject(_mutex, INFINITE);
    uint first = _first;
    if (  _first == _length)
        _first = 0;
    _count--;
    ReleaseMutex(_mutex);
    ReleaseSemaphore(_free_sem, 1, NULL);
    return _data[first];

}
  

оба семафора и мьютекс инициализируются в конструкторе:

 template<typename elem_t>
BlockingQueue<elem_t>::BlockingQueue(uint length) {

    _data = new elem_t [length];
    _length = length;
    _count  =  0;
    _first  =  0;
    _last   = -1;
    _mutex    = CreateMutex(NULL, false, NULL);
    _free_sem = CreateSemaphore(NULL, _length, INFINITE, NULL);
    _used_sem = CreateSemaphore(NULL, _count,  INFINITE, NULL);

}
  

Есть идеи, почему я получаю такую странную ошибку?

РЕДАКТИРОВАТЬ: ошибка 183 произошла из-за неправильной проверки ошибок, поскольку она была перезаписана другой ошибкой перед вызовом GetLastError(). После исправления это всего лишь 6 (ERROR_INVALID_HANDLE), что гораздо более значимо.

Комментарии:

1. Проверка ошибок очень часто ошибочна. Публикация кода, который вообще не проверяет, не помогает нам помочь вам.

2. (1) Покажите код, который использует эти функции. (2) Показать код, который фактически проверяет возвращаемое значение WaitForSingleObject и вызывает GetLastError .

3. Ах да, я понял вашу точку зрения. Вы правы, GetLastError был вызван слишком поздно, когда ошибка уже была перезаписана чем-то другим, теперь у меня 6 (ERROR_INVALID_HANDLE)

4. На самом деле нет смысла обращаться за помощью, когда мы не видим код. Пожалуйста, покажите код с некоторой проверкой ошибок. Опять же, вполне вероятно, что вы неправильно проверили ошибку. Мы не можем сказать вам, что вы сделали неправильно, пока вы не покажете код.

Ответ №1:

Вы не проверяете возвращаемое значение CreateSemaphore . Вполне вероятно, что в этом случае происходит сбой или, если он выполняется успешно, создается «невозможный» семафор. Это связано с использованием INFINITE вами параметра для максимального количества. Аргумент максимального количества имеет значение signed long, INFINITE предназначен для использования с длительностью в миллисекунду без знака, и если вы интерпретируете как значение signed LONG, в итоге вы получите -1. В документации указано, что максимальное значение счетчика должно быть выше 0. При создании ваших семафоров используйте LONG_MAX вместо INFINITE .

Комментарии:

1. Да, это оно! INFINITE не был подписан, поэтому он был подписан -1. Замена его на LONG_MAX решила проблему.