EWOULDBLOCK эквивалентная ошибка под Windows Perl
-
02-07-2019 - |
Вопрос
Добрый день, Stackoverflowers,
Я автор Perl автоумирание прагма, которая изменяет встроенные функции Perl, чтобы они выдавали исключения в случае сбоя.Это похоже на Фатальный, но с лексической областью видимости, расширяемой моделью исключений, более интеллектуальной проверкой возврата и гораздо более приятными сообщениями об ошибках.Он будет заменять Fatal
модуль в будущих выпусках Perl (предварительно 5.10.1+), но в настоящее время его можно загрузить с CPAN для Perl 5.8.0 и выше.
Следующий выпуск autodie
добавит специальную обработку вызовов на flock
с LOCK_NB
(неблокирующий) вариант.В то время как неудачный flock
вызов обычно приводит к исключению в autodie
, неудачный вызов flock
с использованием LOCK_NB
просто вернет false, если возвращено errno ($!
) является EWOULDBLOCK
.
Причина этого в том, что люди могут продолжать писать такой код:
use Fcntl qw(:flock);
use autodie; # All perl built-ins now succeed or die.
open(my $fh, '<', 'some_file.txt');
my $lock = flock($fh, LOCK_EX | LOCK_NB); # Lock the file if we can.
if ($lock) {
# Opportuntistically do something with the locked file.
}
В приведенном выше коде блокировка не удалась, поскольку файл уже заблокирован кем-то другим (EWOULDBLOCK
) не считается серьезной ошибкой, поэтому автоматическое затухание flock
просто возвращает ложное значение.В ситуации, когда мы работаем с файловой системой, которая не поддерживает блокировку файлов, или с сетевой файловой системой, и сеть только что умерла, происходит автоматическое закрытие flock
генерирует соответствующее исключение, когда видит, что наша ошибка не является EWOULDBLOCK
.
Это прекрасно работает в моей версии для разработчиков в системах с поддержкой Unix, но ужасно не работает под Windows.Похоже, что хотя Perl под Windows поддерживает LOCK_NB
опция, она не определяет EWOULDBLOCK
.Вместо этого при возникновении блокировки возвращается ошибка 33 («Ошибка домена»).
Очевидно, я могу жестко запрограммировать это как константу в autodie
, но это не то, что я хочу здесь делать, потому что это означает, что я облажался, если ошибка когда-либо изменится (или изменилась).Я хотел бы сравнить его с эквивалентом Windows POSIX::EWOULDBLOCK
, но я не могу хоть убей найти, где бы такая вещь была определена.Если вы можете помочь, дайте мне знать.
Ответы, которые мне конкретно не нужны:
- Предложения жестко запрограммировать его как константу (или, что еще хуже, оставить плавающее магическое число).
- Не поддерживает
LOCK_NB
функциональность вообще под Windows. - Предполагая, что любой отказ от
LOCK_NB
позвонитьflock
должен возвращать просто false. - Предложения, которые я задаю на p5p или Перлмонкс.Я уже знаю о них.
- Объяснение того, как
flock
, или исключения, илиFatal
работа.Я уже знаю.Интимно.
Решение
Обратите внимание, что в «родном» Perl Win32 $^E имеет более наглядное значение 33: «Процесс не может получить доступ к файлу, потому что другой процесс заблокировал часть файла», что ERROR_LOCK_VIOLATION
(Доступна с Win32::WinError).
Другие советы
Для кода ошибки, специфичного для Windows, вы хотите использовать $^E
.В данном случае это 33:"Процесс не может получить доступ к файлу, поскольку другой процесс заблокировал часть файла" (ERROR_LOCK_VIOLATION
в winerror.h
).
К сожалению, я не думаю Win32::WinError находится в ядре.С другой стороны, если бы Microsoft когда-нибудь изменила нумерацию кодов ошибок Windows, почти каждая когда-либо написанная программа для Windows перестанет работать, поэтому я не думаю, что возникнут проблемы с ее жестким кодированием.