Перекрывающийся файл чтения Win32 на COM-порту, возвращающий ERROR_OPERATION_ABORTED

Хорошо, один для ТАК коллективного разума ...

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

При попытке проверить новое устройство мой код был завален 995 ошибками ERROR_OPERATION_ABORTED, вызывающими GetOverlappedResult после ReadFile. Иногда чтение работало, иногда я получал эту ошибку. Просто игнорирование ошибки и повторная попытка - что удивительно - сработают без потери данных. Никакой ClearCommError не требуется.

Вот отрывок.

if (!ReadFile(handle,&c,1,&read, &olap))
    {
        if (GetLastError() != ERROR_IO_PENDING)
        {
            logger().log_api(LOG_ERROR,"ser_rx_char:ReadFile");
            throw Exception("ser_rx_char:ReadFile");
        }
    }

    WaitForSingleObjectEx(r_event, INFINITE, true);  // alertable, so, thread can be closed correctly.

    if (GetOverlappedResult(handle,&olap,&read, TRUE) != 0)
    {
        if (read != 1)
            throw Exception("ser_rx_char: no data");

        logger().log(LOG_VERBOSE,"read char %d ( read = %d) ",c, read);
    }
    else
    {
        DWORD err = GetLastError();
        if (err != 995)   //Filters our ERROR_OPERATION_ABORTED
        {
            logger().log_api(LOG_ERROR,"ser_rx_char: GetOverlappedResult");
            throw Exception("ser_rx_char:GetOverlappedResult");
        }
    }

Мое первое предположение - виноват драйвер COM-порта, который я раньше не использовал (это порт RS422 на Blackmagic Decklink, к сведению), но это похоже на отговорку.

Ну и Vista SP1 Business 32-bit, за мои грехи.

Прежде чем я просто отнесу это к «чужой проблеме», есть ли у кого-нибудь идеи о том, что может вызвать это?

Я не верю, что это ваша проблема, но вы неправильно используете WaitForSingleObjectEx. Вы должны искать (1) dwWait == WAIT_OBJECT_0 или (2) dwWait == WAIT_TIMEOUT && dwError == ERROR_IO_PENDING.

jww 20.09.2012 21:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
9 335
2

Ответы 2

Как вы настраиваете структуру OVERLAPPED перед ReadFile? - Я всегда обнуляю их (кроме hEvent, очевидно), что, возможно, отчасти является суеверием, но у меня такое чувство, что это вызывало у меня проблемы в прошлом.

Боюсь, винить драйвер (если он не MS, а не просто небольшая настройка из справочника) не совсем нереально. Написать драйвер COM - невероятно сложная вещь, и сложность его тестирования состоит в том, что каждое когда-либо написанное приложение использует последовательные порты и их IOCTL несколько по-разному.

Другая распространенная проблема - не настроить весь порт - например, не вызывать SetCommTimeouts или SetupComm. Понятия не имею, совершаете ли вы такого рода ошибку, но я встречал людей, которые говорили, что не используют тайм-ауты, когда на самом деле имели в виду, что они не вызывали SetCommTimeouts, поэтому они используют их, но у них нет понятие, на что они настроены ...

Такие вещи могут быть убийственными для сторонних драйверов COM, потому что людям часто сошло с рук всякая старая ерунда с драйвером MS, и он не всегда работает одинаково с другим устройством.

Я согласен с тем, что тайм-ауты выглядят вероятной причиной, особенно потому, что ввод не теряется, а вызов ReadFile читает только один байт за раз. Однако, если приложение правильно настраивает порт, вполне реально винить драйвер, в том числе драйвер MS.

Windows programmer 21.11.2008 02:49

Я очищаю структуру OVERLAPPED (кроме hEvent) и вызываю SetCommTimeouts с нулями во всех полях в COMMTIMEOUTS. Я попытался перейти на ввод / вывод без перекрытия и получил тот же результат. Пора попробовать другой порт связи ...

Roddy 21.11.2008 12:46

помимо обнуления OVERLAPPED, вы также можете проверить, как вы устанавливаете olap.hEvent, то есть каковы ваши аргументы CreateEvent? Если вы создаете событие с предварительным сигналом (т.е. третий аргумент CreateEvent - ИСТИНА), я бы ожидал немедленного возврата. Кроме того, не забывайте, что если вы укажете manualReset (второй аргумент CreateEvent) как FALSE, GetOverlappedResult () поможет вам очистить событие, что может объяснить, почему он работает во второй раз.

Не могу сказать из вашего фрагмента, влияет ли это на вас - надеюсь, это поможет.

Другие вопросы по теме