FreeBSD, MySQL, Perl, bash: прерывистая блокировка именованных каналов? - PullRequest
2 голосов
/ 31 октября 2009

Это странно, и я не уверен, кто на самом деле виновник.

Я занимаюсь написанием сценариев во FreeBSD (6.2)? который широко использует следующее *** bash *** ism:

do_something <(mysql --skip-column-names -B -e 'select ... from ... where ...;')

... где "do_something" - довольно грубая утилита (в Perl), которая не читает из конвейера. Если я использую обычный файл, он работает нормально. Мой скрипт bash использует такие вещи, как exec 4< <(...) с такими запросами (после циклов вида while read x y z <&4; do ..., похоже, никогда не возникает проблем.

Однако Perl (5.8.x), кажется, периодически блокируется (по-видимому, навсегда). Я попытался изменить chomp(my $data = <MYDATA>); с помощью подпрограммы, которая использовала sysread , и я написал несколько тестовых случаев в Python для сравнения. Кажется, что они блокируют гораздо реже, чем идиоматический код Perl, но иногда они все же делают это. (Код Python, использующий f.read() или os.read(f.fileno()...), кажется, ведет себя примерно одинаково в этом вопросе.)

Я пытался воспроизвести проблему, используя ... <(cat ...) (где я кошка в обычном файле), и это никогда не воспроизводит этот киоск.

Я взглянул на некоторые данные ktrace / kdump ... но я гораздо лучше знаком с Linux strace или даже с Solaris truss .. так что я еще не выяснил, что будет дальше.

Полагаю, мы в основном можем исключить Perl, потому что я воспроизвел ту же проблему, используя Python ... Я не понимаю, как bash мог бы делать что-то здесь не так (это просто создание именованный канал в / var / tmp / sh-np-xxx и подключение процессов к этому).

Что может делать оболочка / утилита mysql , которая может вызвать это? Я не думаю, что видел это от чего-то еще (например, cat или dd ). Я не тестировал этот сценарий под Linux ... но я использовал <(...) (процесс подстановки) в течение многих лет под Linux и не помню, чтобы когда-либо видел это.

Это проблема FreeBSD?

Конечно, я могу обойти эту проблему, используя временные файлы ... но я бы скорее понял, почему это происходит (и избегаю некоторых гонок и беспорядка очистки, которые влекут за собой временные файлы).

Есть предложения?

1 Ответ

4 голосов
/ 31 октября 2009

Большая разница между работой над выводом mysql и непосредственно над файлом заключается в синхронизации. Когда процесс perl остановлен, возникает большой вопрос: «почему он не продвигается вперед»? Вы можете использовать опцию «l» для ps, чтобы увидеть канал ожидания для процесса perl; Таким образом, вы можете увидеть, заблокирован ли он при чтении или происходит что-то еще. Если он действительно заблокирован на входе канала, я ожидаю, что запись MWCHAN для perl будет "piperd".

Та же информация была бы интересна для процесса mysql.

Как выглядит ваш тестовый код Python?

Другой способ написать это, избегая при этом башизма, - это; это позволило бы вам исключить bash:

mysql --skip-column-names -B -e 'select ... from ... where ...;' | do_something /dev/stdin

Другие интересные вопросы:

  • Изменяет ли параметр --unbuffered для mysql что-нибудь?

  • Изменяет ли что-либо изменение в конвейере вывода mysql через dd? (напр. "perlscript <(mysql ... | dd) </p>

Резюме: нужна дополнительная информация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...