EWOULDBLOCK эквивалентно errno под Windows Perl - PullRequest
10 голосов
/ 25 сентября 2008

G'day Stackoverflowers,

Я являюсь автором прагмы autodie в Perl, которая изменяет встроенные функции 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. Вместо этого возвращается errno 33 («Ошибка домена»), когда происходит блокировка.

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

Ответы, которые я специально не хочу:

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

Ответы [ 2 ]

11 голосов
/ 25 сентября 2008

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

5 голосов
/ 25 сентября 2008

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

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

...