пары сокетов, perl, KEEPALIVE и опрос - PullRequest
2 голосов
/ 15 декабря 2009

Я начал использовать пары сокетов в linux и windows, чтобы захватить выходные данные подпроцессов на обеих платформах. Я делаю это, копируя STD * на один из сокетов в паре сокетов (я использую Win32 :: SocketPair в perl для сокетов пар в Windows). Основная причина, по которой я это делаю, заключается в том, что read НЕ блокирует дескрипторы выходного файла.

Проблема, с которой я столкнулся, заключается в том, что kill (0, ...) не работает в Windows, поэтому мне нужен другой способ определить, что процесс не работает. Я посмотрел на SO_KEEPALIVE, но, похоже, это не работает с парами сокетов ... Я использовал setsockopt (...), затем getsockopt (...) и опция SO_KEEPALIVE была отключена до и после вызова setsockopt ().

Затем я начал изучать опрос событий в сокете. Событие POLLHUP выглядело многообещающе, но я не уверен, что оно работает, когда они используются таким образом.

Я пытаюсь автоматизировать интерактивные программы (нет, я не могу использовать, кроме как, поскольку он не работает на платформах Windows ... если вы не нашли ту, которая работает?). Я тестировал "cat" в Windows (у меня установлен cat.exe). Пока это выглядело хорошо, но есть 2 вопроса:

  • не может определить, просто ли умирает процесс (kill (0, ...) не работает)
  • не может обнаружить EOF из подпроцесса (похоже, sysread всегда возвращает undef или прочитанные байты, никогда 0, даже после того, как я выключился ($ sock, 1))

Возможно, я делаю что-то чрезвычайно глупое, но любой совет / помощь будут признательны.

ОБНОВЛЕНИЕ: я начал использовать waitpid ($ pid, WNOHANG), чтобы обнаружить условие «все еще работает», которое помогает, поскольку кажется, что процесс всегда умирает после того, как все прочитано. waitpid возвращает 0, если pid все еще работает. Тем не менее, это не EOF, это лучше, чем ничего, но я все еще ищу другой вклад. Это, очевидно, не идеально.

ОБНОВЛЕНИЕ 2: Этот Q / A помог с EOF частью моего вопроса, не идеально, но лучше: Как epoll обнаруживает закрытие клиентской стороны в Python?

Ответы [ 2 ]

1 голос
/ 15 декабря 2009

Если это поддерживается в среде WIN32, и ваш процесс порождает дочерние процессы, вы можете попытаться настроить обработчик сигнала для перехвата сигнала SIGCHLD от порожденных процессов в родительском процессе ... что-то вроде:

$ SIG {CHLD} = sub { печать "поймал sigchld от дочернего процесса"; };

Это должно сказать вам, если один из подпроцессов завершился.

0 голосов
/ 15 декабря 2009

В Linux вы можете установить сокет как неблокирующий (начиная с версии 5.8):

 $socket->blocking(0);   # or (*SOCKET)->blocking(0);

Это не работает в Windows (ну, может быть, в 5.10), но вы можете использовать 4-аргументный вызов выбора, чтобы увидеть, есть ли входные данные в сокете, прежде чем пытаться его прочитать (и в Windows 4-arg select работает только с дескрипторами сокетов, но не с файловыми дескрипторами или каналами).

Если вам все еще нужно сказать, активен ли процесс Windows (с известным PID), оформите Win32 :: Process :: Open метод , который попытается открыть дескриптор процесса Windows и вернуть ноль при ошибке.


РЕДАКТИРОВАТЬ: Я не заметил раньше, что вы сказали, что сокеты происходят из подпроцессов. В этом случае вы можете просто позвонить

waitpid $pid, WNOHANG;   # and    use POSIX ':sys_wait_h'

в любое время. Когда waitpid не возвращает -1, вы знаете, что процесс мертв.

...