IPC :: Open3 не работает под Apache - PullRequest
6 голосов
/ 20 января 2010

У меня есть модуль, который использует IPC :: Open3 (или IPC :: Open2, оба демонстрируют эту проблему) для вызова внешнего двоичного файла (в данном случае bogofilter) и передачи ему некоторого ввода через дескриптор файла дочернего ввода, а затем читаетрезультат из дескриптора дочернего вывода.Код работает нормально при запуске в большинстве сред.Тем не менее, основное использование этого модуля в веб-сервисе, работающем под Apache 2.2.6.И в этой среде я получаю сообщение об ошибке:

Невозможно fdopen STDOUT: неверный аргумент

Это происходит только тогда, когда код выполняется под Apache.Ранее код создавал ужасно сложную команду, которая включала здесь документ для ввода и запускала его с обратными галочками.Это сработало, но было очень медленным и склонным к взлому уникальными и сбивающими с толку способами.Я не хотел бы возвращаться к старой версии, но я не могу взломать это.

Ответы [ 4 ]

1 голос
/ 20 января 2010

Может ли быть так, что mod_perl 2 закрывает STDOUT? Я только что обнаружил это и написал об этом:

http://marc.info/?l=apache-modperl&m=126296015910250&w=2

Я думаю, что это неприятный баг, но пока никому до этого нет дела. Опубликуйте продолжение в списке mod_perl, если ваша проблема связана, и вы хотите, чтобы она привлекла внимание.

Jon

0 голосов
/ 19 июня 2014

Caveat Emptor: я не волшебник Perl.

Как и предположил @JonathanSwartz, я считаю, что проблема в том, что apache2 mod_perl закрывает STDIN и STDOUT.Это не должно относиться к тому, что делает IPC :: Open3, но в нем есть ошибка, описанная здесь .

В заключение (это часть, я не суперснимите флажок), open3 пытается сопоставить дочерние процессы STDIN / OUT / ERR с вашим процессом или продублировать его, если это было запрошено.Из-за недокументированных способов работы open ('> & = X') он обычно работает нормально, за исключением случая, когда закрыты STDIN / OUT / ERR.

Другая ссылка , котораяуглубляется в детали.

Одним из решений является исправление IPC :: Open3, как описано в обеих этих ссылках.Другой, который работал для меня, это временно открыть STDIN / OUT в вашем коде mod_perl, а затем закрыть его:

my ($save_stdin,$save_stdout);
open $save_stdin, '>&STDIN';
open $save_stdout, '>&STDOUT';
open STDIN, '>&=0';
open STDOUT, '>&=1';

#make your normal IPC::Open3::open3 call here

close(STDIN);
close(STDOUT);
open STDIN, '>&', $save_stdin;
open STDOUT, '>&', $save_stdout;

Кроме того, я заметил кучу жалоб в сети по поводу IPC :: Run3страдает от тех же проблем, поэтому, если кто-то столкнется с той же проблемой, я подозреваю, что будет работать то же самое решение.

0 голосов
/ 06 июня 2011

Если ваш код будет запускаться только в системах Linux / Unix, легко написать замену open3, которая не даст сбоя, потому что STDOUT не является реальным дескриптором файла:

sub my_open3 {
    # untested!
    pipe my($inr), my($inw) or die;
    pipe my($outr), my($outw) or die;
    pipe my($errr), my($errw) or die;
    my $pid = fork;
    unless ($pid) {
        defined $pid or die;
        POSIX::dup2($inr, 0);
        POSIX::dup2($outw, 1);
        POSIX::dup2($errw, 2);
        exec @_;
        POSIX::_exit(1);
    }
    return ($inw, $outr, $errr);
}

my ($in, $out, $err) = my_open3('ls /etc/');
0 голосов
/ 06 июня 2011

Bogofilter возвращает различные коды выхода для спама / не спама.

Вы можете «исправить» это, перенаправив стандартный вывод в / dev / null

system("bogofilter < $input > /dev/null") >> 8;

Вернет 0 для спама, 1 дляnonspam, 2 для неизвестного (>> 8 - потому что perl услужливо исправляет код выхода, это исправляет повреждение).

Примечание: отсутствие среды также может помешать bogofilter найти свой список слов, поэтому передайтев явном виде также:

system("bogofilter -d /path/to/.bogofilter/ < $input > /dev/null") >> 8;

(где /path/to/.bogofilter содержит wordlist.db)

Вы не можете получить фактическую оценку, которую bogofilter дал таким образом, ноэто вам что-то даст.

...