Эквивалент EWOULDBLOCK errno в Windows Perl

Добрый день, Stackoverflowers,

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

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

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

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

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

person pjf    schedule 25.09.2008    source источник


Ответы (2)


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

person tye    schedule 25.09.2008
comment
Великолепно! Именно то, что я ищу! Большое тебе спасибо! - person pjf; 25.09.2008

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

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

person cjm    schedule 25.09.2008
comment
Это именно то, что я ищу! Я не слишком обеспокоен тем, что Win32::WinError не является ядром. Если он существует, я могу вытащить из него константу. Если это не так, я всегда могу вернуться к жестко запрограммированному (но неприглядному) значению 33. Еще раз спасибо! Павел - person pjf; 25.09.2008
comment
Win32::WinError, скорее всего, находится в ядре Windows, то есть в одном из модулей, входящих в каждый дистрибутив Perl для Win32 (как и все в комплекте libwin32). - person tye; 25.09.2008