Прошло 3 года, и Windows 8 была выпущена. Благодаря регрессии, введенной в реализации консоли в Windows 8, я должен был что-то сделать с проблемой, которая вызвала этот вопрос. Итак, я наконец попытался использовать вызов функции ReOpenFile ().
В одном предложении: для моих целей это бесполезно.
ReOpenFile () API используется для «получения существующего дескриптора файла и получения другого дескриптора с другим набором прав доступа». По крайней мере, это указано в оригинальной статье .
Я пытался использовать ReOpenFile () на дескрипторе ввода консоли:
stdin_in = GetStdHandle(STD_INPUT_HANDLE);
stdin_in_operlapped = ReOpenFile(stdin_in, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, FILE_FLAG_OVERLAPPED);
if (stdin_in_operlapped == INVALID_HANDLE_VALUE)
{
my_debug("failed to ReOpen stdin handle with OVERLAPPED flag: %d", GetLastError());
exit(1);
}
И что я получаю: ошибка 1168: «Элемент не найден». «Спасибо, Microsoft». Я даже не буду пытаться использовать его для анонимных каналов, поскольку в документации говорится:
«Асинхронные (перекрывающиеся) операции чтения и записи не поддерживаются анонимными каналами. Это означает, что вы не можете использовать функции ReadFileEx и WriteFileEx с анонимными каналами. Кроме того, параметр lpOverlapped в ReadFile и WriteFile игнорируется, когда эти функции используются с анонимными каналами. ”
Спасибо вам, люди, все за ваши предложения. При асинхронном чтении из дескриптора необходимо быть готовым к тому, что операция может завершиться синхронно. Что я знаю. Основная причина, по которой я задавал этот вопрос:
когда было выполнено синхронное чтение для некоторых объектов (по крайней мере, анонимных каналов и консольного ввода в Windows 8), тогда вызов CloseHandle () из другого потока на том же дескрипторе либо завершится ошибкой, либо зависнет, пока ReadFile () завершается; это означает, что он будет зависать бесконечно во многих случаях. Вот почему я хотел заменить синхронный дескриптор асинхронным.
Теперь мне ясно, что в операционных системах Windows просто невозможно отменить некоторые операции чтения простым способом. При чтении из синхронных дескрипторов нужно просто выйти из приложения, даже если ReadFile () все еще читает из дескриптора в каком-то потоке, потому что просто невозможно надежно разбудить такую операцию чтения. В курсе ... В более новой ОС эту операцию можно отменить. Однако нет никакого способа узнать, находится ли поток в вызове ReadFile (), или еще нет. Если ReadFile () еще не вызван, то отменить операцию невозможно, и последующее чтение будет зависать. Единственным способом было бы закрыть дескриптор, но эта операция зависает или дает сбой на некоторых объектах и в некоторых операционных системах. Единственное правильное решение для этого - асинхронный ввод-вывод. Но, как я упоминал в начале, наше приложение запускается сторонними приложениями, и мы не можем заставить их всех всегда создавать именованные каналы с перекрывающимся флагом, установленным для stdio.
Я сдаюсь и собираюсь реализовать мерзкие уродливые хаки ... нам придется продолжать читать без структуры OVERLAPPED из HANDLE, которые были созданы с флагом OVERLAPPED, и с утечкой дескрипторов и потоков ....