EWOULDBLOCK эквивалент errno под Windows Perl

G'day Stackoverflowers,

Я автор Perl autodie pragma, который изменяет встроенные в Perl блокировки исключений при сбое. Он похож на Fatal, но с лексической областью, расширяемой моделью исключений, более интеллектуальной проверкой возврата и гораздо более приятными сообщениями об ошибках. Он будет заменять модуль 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), не считается жесткой ошибкой, поэтому autodying flock просто возвращает значение false. В ситуации, когда мы работаем с файловой системой, которая не поддерживает файловые блокировки, или сетевая файловая система и сеть просто умерли, тогда autodying flock генерирует соответствующее исключение, когда видит, что наша ошибка не EWOULDBLOCK.

Это отлично работает в моей dev-версии на Unix-ароматизированных системах, но это ужасно терпит неудачу под Windows. Похоже, что хотя Perl под Windows поддерживает параметр LOCK_NB, он не определяет EWOULDBLOCK. Вместо этого возвращаемое errno равно 33 ( "Ошибка домена" ), когда произойдет блокировка.

Очевидно, я могу жестко записать это как константу в autodie, но это не то, что я хочу сделать здесь, потому что это означает, что я ввернута, если errno когда-либо изменяет (или изменилось). Мне бы хотелось сравнить его с эквивалентом Windows POSIX::EWOULDBLOCK, но я не могу в жизни меня найти, где такое будет определено. Если вы можете помочь, сообщите мне.

Ответы, которые я конкретно не хочу:

  • Предложения жестко закодировать его как константу (или, что еще хуже, оставить плавающее магическое число).
  • Не поддерживает LOCK_NB функциональность вообще под Windows.
  • Предполагая, что любой сбой вызова LOCK_NB на flock должен возвращать только false.
  • Предложения, которые я задаю на p5p или perlmonks. Я уже знаю о них.
  • Объяснение того, как flock, или исключения, или Fatal работают. Я уже знаю. Тесно.

Ответ 1

В Win32 "native" Perl обратите внимание, что $^ E более описателен в 33, "Процесс не может получить доступ к файлу, потому что другой процесс заблокировал часть файла", который равен ERROR_LOCK_VIOLATION (доступен из Win32:: WinError).

Ответ 2

Для кода ошибки, специфичного для Windows, вы хотите использовать $^E. В этом случае он 33: "Процесс не может получить доступ к файлу, потому что другой процесс заблокировал часть файла" (ERROR_LOCK_VIOLATION в winerror.h).

К сожалению, я не думаю, что Win32:: WinError находится в ядре. С другой стороны, если Microsoft когда-либо перенумеровала коды ошибок Windows, почти каждая работающая в Windows программа перестала бы работать, поэтому я не думаю, что проблема с жесткой кодировкой будет.