The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Как отследить форкнутый процесс"
Вариант для распечатки Архивированная нить - только для чтения! 
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Как отследить форкнутый процесс"
Сообщение от forfreeuse emailИскать по авторуВ закладки(??) on 13-Май-04, 10:58  (MSK)
Пытаюсь написать фильтр к внешней программе (например popa3d).

юзер <--> фильтр <--> popa3d

все работают через стандартный вход/выход.
Создаю пайпы на вход/выход, форкаю popa3d, dup'лю вход/выход popa3d на свои файловые дескрипторы.
Все работает, за исключением одного но, никак не могу отследить момент завершения popa3d.
Запускаю фильтр:
bash-2.05b# ./test
+OK
USER VASIA
+OK
QUIT
+OK
test
Broken pipe
bash-2.05b#

После того, как popa3d получил QUIT, он ответил и вышел, попытка послать ему что-то еще приводит к Broken pipe.

А как определить из фильтра, что popa3d вышел?
Или я что-то делаю не так?

#include <stdio.h>
#include
#include <string.h>
#include <errno.h>

int main (void)
{
int in[2],out[2];
char child_prog[]="/usr/sbin/popa3d";
FILE *child_out,*child_in;
int pid;
char tmp[1024];


//Make pipes
if (pipe(in))
{
printf("%s","Can't make in pipe\n");
exit(-1);
}
if (pipe(out))
{
printf("%s","Can't make out pipe\n");
exit(-1);
}

//Fork
pid=fork();
if (pid<0)
{
printf("%s","Can't fork\n");
exit(-1);
}


else if (pid==0)
{ //child
close(out[0]);
close(in[1]);

dup2(in[0],STDIN_FILENO);
dup2(out[1],STDOUT_FILENO);
if (execlp(child_prog,child_prog,NULL)<0)
{
printf ("ERROR: Can't start %s: %s\n",child_prog, strerror(errno));
exit(-1);
}
exit(0);
}


//parent
close(in[0]);
close(out[1]);

if ((child_out=fdopen(in[1],"w"))==NULL)
{
printf("Can't fdopen out streem for child\n");
exit(-1);
}
if ((child_in=fdopen(out[0],"r"))==NULL)
{
printf("Can't fdopen input streem for child\n");
exit(-1);
}

//Talk cycle
while(fgets(tmp,1023,child_in)!=NULL)
{
printf("%s",tmp);
fflush(stdout);

//Get from stdin
if (fgets(tmp,1023,stdin)==NULL) {printf("fgets from stdin error\n");exit(0);}
// printf("get: %s\n",tmp);

//Write to child
if(fputs(tmp,child_out)==EOF) {printf("fput to child error\n");exit(0);}
if(fflush(child_out)==EOF) {printf("fflush child_out error\n");exit(0);}
}

}
  Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "Как отследить форкнутый процесс"
Сообщение от vnp emailИскать по авторуВ закладки on 13-Май-04, 22:05  (MSK)
>Пытаюсь написать фильтр к внешней программе (например popa3d).
>
> юзер <--> фильтр <--> popa3d
>
> все работают через стандартный вход/выход.
> Создаю пайпы на вход/выход, форкаю popa3d, dup'лю вход/выход popa3d на свои
>файловые дескрипторы.
> Все работает, за исключением одного но, никак не могу отследить момент
>завершения popa3d.

Рекомендую select с проверкой (среди прочего) out[0] на читаемость. Как только окажется, что он готов для чтения, читать. Если read вернет 0, значит трубу закрыли.
После этого, разумеется, wait.

> Запускаю фильтр:
> bash-2.05b# ./test
> +OK
> USER VASIA
> +OK
> QUIT
> +OK
> test
> Broken pipe
> bash-2.05b#
>
> После того, как popa3d получил QUIT, он ответил и вышел, попытка
>послать ему что-то еще приводит к Broken pipe.
>
> А как определить из фильтра, что popa3d вышел?
> Или я что-то делаю не так?
>
> #include <stdio.h>
> #include
> #include <string.h>
> #include <errno.h>
>
> int main (void)
> {
> int in[2],out[2];
> char child_prog[]="/usr/sbin/popa3d";
> FILE *child_out,*child_in;
> int pid;
> char tmp[1024];
>
>
> //Make pipes
> if (pipe(in))
> {
> printf("%s","Can't make in pipe\n");
> exit(-1);
> }
> if (pipe(out))
> {
> printf("%s","Can't make out pipe\n");
> exit(-1);
> }
>
> //Fork
> pid=fork();
> if (pid<0)
> {
> printf("%s","Can't fork\n");
> exit(-1);
> }
>
>
> else if (pid==0)
> { //child
> close(out[0]);
> close(in[1]);
>
> dup2(in[0],STDIN_FILENO);
> dup2(out[1],STDOUT_FILENO);
> if (execlp(child_prog,child_prog,NULL)<0)
> {
> printf ("ERROR: Can't start %s: %s\n",child_prog, strerror(errno));
> exit(-1);
> }
> exit(0);
> }
>
>
> //parent
> close(in[0]);
> close(out[1]);
>
> if ((child_out=fdopen(in[1],"w"))==NULL)
> {
> printf("Can't fdopen out streem for child\n");
> exit(-1);
> }
> if ((child_in=fdopen(out[0],"r"))==NULL)
> {
> printf("Can't fdopen input streem for child\n");
> exit(-1);
> }
>
> //Talk cycle
> while(fgets(tmp,1023,child_in)!=NULL)
> {
> printf("%s",tmp);
> fflush(stdout);
>
> //Get from stdin
> if (fgets(tmp,1023,stdin)==NULL) {printf("fgets from stdin error\n");exit(0);}
> // printf("get: %s\n",tmp);
>
> //Write to child
> if(fputs(tmp,child_out)==EOF) {printf("fput to child error\n");exit(0);}
> if(fflush(child_out)==EOF) {printf("fflush child_out error\n");exit(0);}
> }
>
> }


  Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "Как отследить форкнутый процесс"
Сообщение от forfreeuse emailИскать по авторуВ закладки(??) on 14-Май-04, 12:13  (MSK)
Он падает не на попытке чтения, а на попытке записи
> //Write to child
> if(fputs(tmp,child_out)==EOF) {printf("fput to child error\n");exit(0);}
Здесь еще живой
> if(fflush(child_out)==EOF) {printf("fflush child_out error\n");exit(0);}
А вот от fflush падает.

Попробовал select, не помогает. Так же пробовал читать коды возврата от write и fflush, feof,ferror,fileno...

Везде одно и тоже, тестирование показывает, что все в порядке, а операция fflush завершает программу и печатает сообщение Broken pipe.

Похоже в pipe, свои, внутренние проверки, которые останавливают прогу и печатают свое сообщение об ошибке...

Может быть как-то еще, не через pipe можно такое сделать...

  Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "Как отследить форкнутый процесс"
Сообщение от vnp emailИскать по авторуВ закладки on 14-Май-04, 22:27  (MSK)
>Он падает не на попытке чтения, а на попытке записи

Об чем и речь. Проверяем читаемость только для того, чтобы определить жива ли труба. Комбинация условий "чтение не заблокируется" и "read возвращает 0" означает, что труба закрылась.

>> //Write to child
>> if(fputs(tmp,child_out)==EOF) {printf("fput to child error\n");exit(0);}
>Здесь еще живой
>> if(fflush(child_out)==EOF) {printf("fflush child_out error\n");exit(0);}
>А вот от fflush падает.
>
>Попробовал select, не помогает. Так же пробовал читать коды возврата от write
>и fflush, feof,ferror,fileno...
>
>Везде одно и тоже, тестирование показывает, что все в порядке, а операция
>fflush завершает программу и печатает сообщение Broken pipe.
>
>Похоже в pipe, свои, внутренние проверки, которые останавливают прогу и печатают свое
>сообщение об ошибке...

Broken pipe печатает хандлер SIGPIPE. Можно, конечно, установить свой... тоже решение...

>Может быть как-то еще, не через pipe можно такое сделать...


  Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "Как отследить форкнутый процесс"
Сообщение от forfreeuse emailИскать по авторуВ закладки(??) on 17-Май-04, 09:58  (MSK)
Спасибо за помощь, вроде как все заработало.
Однако рецепт не совсем очевиден, не подскажите, откуда такие познания?
А как у такой конструкции с переносимостью? На разных никсах будет работать?

>>Он падает не на попытке чтения, а на попытке записи
>
>Об чем и речь. Проверяем читаемость только для того, чтобы определить жива
>ли труба. Комбинация условий "чтение не заблокируется" и "read возвращает 0"
>означает, что труба закрылась.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "Как отследить форкнутый процесс"
Сообщение от klalafuda Искать по авторуВ закладки on 17-Май-04, 19:59  (MSK)
>Спасибо за помощь, вроде как все заработало.
>Однако рецепт не совсем очевиден, не подскажите, откуда такие познания?
>А как у такой конструкции с переносимостью? На разных никсах будет работать?
>
>
>>>Он падает не на попытке чтения, а на попытке записи
>>
>>Об чем и речь. Проверяем читаемость только для того, чтобы определить жива
>>ли труба. Комбинация условий "чтение не заблокируется" и "read возвращает 0"
>>означает, что труба закрылась.

почитайте "UNIX" Робачевского. откроете для себя много нового и полезного :)

// wbr

  Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "Как отследить форкнутый процесс"
Сообщение от forfreeuse emailИскать по авторуВ закладки(??) on 17-Май-04, 22:26  (MSK)
Читал, ответа там не нашел.
На мой взгляд пайпы там описаны довольно таки скудно.
Тем более не описана ситуация, когда форкнутый процесс отмерает.

>почитайте "UNIX" Робачевского. откроете для себя много нового и полезного :)
>
>// wbr


  Рекомендовать в FAQ | Cообщить модератору | Наверх

8. "Как отследить форкнутый процесс"
Сообщение от klalafuda Искать по авторуВ закладки on 18-Май-04, 08:26  (MSK)
>Читал, ответа там не нашел.
>На мой взгляд пайпы там описаны довольно таки скудно.
>Тем более не описана ситуация, когда форкнутый процесс отмерает.
>
>>почитайте "UNIX" Робачевского. откроете для себя много нового и полезного :)
>>
>>// wbr

странно, я там в свое время нащел практически все что нужно. ну и далее man man конечно же..

в довесок посмотрите Стивенса "UNIX взаимодействие процессов". там это описано подробнее.

// wbr

  Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "Как отследить форкнутый процесс"
Сообщение от vnp emailИскать по авторуВ закладки on 18-Май-04, 03:10  (MSK)
>Спасибо за помощь, вроде как все заработало.
>Однако рецепт не совсем очевиден, не подскажите, откуда такие познания?

А черт его знает. Из воздуха, как и многое другое.

Однако посмотрел на трезвую голову, и увидел race в простейшем сценарии:
если дочерний процесс завершится между возвратом select и вызовом write, имеем проблему. Так, что SIGPIPE ловить, видимо, надежнее...

>А как у такой конструкции с переносимостью? На разных никсах будет работать?

Если блокирующий read возвращает 0, то гарантировано, что "больше данных не будет". В контексте труб (и сокетов) это значит, что "та сторона" свой конец закрыла. В вашей ситуации, закрытие канала определенно означает завершение процесса; в общем случае такой вывод делать нельзя.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

10. "Как отследить форкнутый процесс"
Сообщение от forfreeuse emailИскать по авторуВ закладки(??) on 18-Май-04, 12:40  (MSK)
В итоге сделал обработчики SIGPIPE и SIGCHLD, думаю так надежнее будет,
плюс проверку select'om.

Спасибо за помощь!

  Рекомендовать в FAQ | Cообщить модератору | Наверх

9. "Как отследить форкнутый процесс"
Сообщение от klalafuda Искать по авторуВ закладки on 18-Май-04, 09:42  (MSK)
>Спасибо за помощь, вроде как все заработало.
>Однако рецепт не совсем очевиден, не подскажите, откуда такие познания?
>А как у такой конструкции с переносимостью? На разных никсах будет работать?
>

да, собственно:
http://www.opengroup.org/onlinepubs/009695399/toc.htm
там все есть.

// wbr

  Рекомендовать в FAQ | Cообщить модератору | Наверх


Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру