The OpenNET Project / Index page

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

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

"FORK()" 
Сообщение от Andrei emailИскать по авторуВ закладки(??) on 12-Июл-05, 20:48  (MSK)
Господа,
Пытаюсь написать мультипоточный TCP daemon который запускает внешнюю программу при сетевом соединении на определенный открытый порт.

При отработки accept() делаю fork() для порождения нового дочернего процесса, в котором будет производиться вызов внешней программы. При вызове внешней программы делаю еще раз fork(), и замещаю образ нового дочернего процесса при помощи execv() образом исполняемой внешней программы. В теле кода родителя делаю waitpid() для ожидания завершения дочернего процесса. Waitpid() возвращает -1 с кодом ошибки errno=ECHILD(No child processes).

При тестировании етого же кода, но без первого fork()a все прекрасно работает.

Никто не подскажет в чем может быть дело ? Можно ли несколько раз порождать fork()ом вложеные дочернии просессы и ждать их завершения внутри родителей waitpidом ?

P.S Операционная система FreeBSD 5.3

  Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

  • FORK(), romanSA, 11:50 , 13-Июл-05, (2)  
    • FORK(), Andrei, 12:59 , 13-Июл-05, (3)  
      • FORK(), romanSA, 02:07 , 14-Июл-05, (4)  
        • FORK(), Andrei, 13:40 , 14-Июл-05, (5)  
          • FORK(), Vladislav, 22:35 , 15-Июл-05, (6)  
            • FORK(), dimus, 10:39 , 25-Июл-05, (7)  

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

2. "FORK()" 
Сообщение от romanSA Искать по авторуВ закладки(??) on 13-Июл-05, 11:50  (MSK)
1. waitpid() ожидает только процесс с указанным в его параметре идентификатором. Какой идентификатор Вы указываете?

2. Как задан обработчик сигнала SIGCHLD? Если SIG_IGN, то Вы будете всегда получать ECHILD.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "FORK()" 
Сообщение от Andrei emailИскать по авторуВ закладки(??) on 13-Июл-05, 12:59  (MSK)
>1. waitpid() ожидает только процесс с указанным в его параметре идентификатором. Какой
>идентификатор Вы указываете?

Примерно вот так:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

#include <setjmp.h>

#define MAX_EPRG_ARGS   10

#define MAX_LEN   5000

#define EXT_PRG_TIMEOUT   30 /* Seconds */

/* For signal processing */

pid_t pid_to_kill   = (-1);

jmp_buf env;

void sig_alrm (int dummy)
{
if (pid_to_kill>0)
  {
   kill (pid_to_kill,9); /* Kill it */
   longjmp (env,1);
  }
}

int execute (char * ext_prg,
char * ext_arg,
char * ext_output,
size_t bufsize)
{
  int rcode = -1;
  int Pipe [2];
  int status = 0;
  char * ARGUMENTS [MAX_EPRG_ARGS];
  char temp_str [5000];
  int i=0;

  int ret_wpd = -1;

  char data [2];

  sig_t prev;

  /* Clear the buffer */

  memset (ext_output,0,bufsize);

  prev=signal (SIGALRM,sig_alrm);

  if (setjmp(env)!=0)
  {
   /* Here returns longjmp */
   if (pid_to_kill>0)
   {
    /* Return the prev sigaction */
    signal (SIGALRM,prev);
    snprintf (temp_str,sizeof(temp_str)-1,"execute(): Timeout waiting external program termination, killing pid: %lu",pid_to_kill);
    write_log (temp_str);
    close (Pipe[0]);
    close (Pipe[1]);
    return (-1);
   }
  }

  if (pipe(Pipe)==-1)
   {
    snprintf (temp_str,sizeof(temp_str)-1,"execute(): Cannot create pipe: '%s' !\n",strerror(errno));
    write_log (temp_str);
    return (-1);
   }

  memset (&temp_str,0,sizeof(temp_str));

  if ((rcode=fork ())==0)  /* Child */
   {
    for (i=0;i<=MAX_EPRG_ARGS-1;i++) ARGUMENTS[i]=NULL;
    ARGUMENTS[0]=ext_prg;
    ARGUMENTS[1]=strtok (ext_arg, " \t");    
    if (ARGUMENTS[1]!=NULL)
     {
       for (i=2;i<=MAX_EPRG_ARGS-1;i++)
        {
         ARGUMENTS[i]=strtok (NULL, " \t");    
         if (ARGUMENTS[i]==NULL) break;
        }
     }

    /* First close the read end of the pipe */

    close (Pipe[0]);    

    /* Make a dup */

    if (dup2(Pipe[1],1)==-1)
     {
      snprintf (temp_str,sizeof(temp_str)-1,"execute(): 'Dup2' command failed: '%s' !\n",strerror(errno));
      write_log (temp_str);
      close (Pipe[0]);
      close (Pipe[1]);
      exit (253);
     }
    
    if (execv(ext_prg,ARGUMENTS)==-1)
     {
      snprintf (temp_str,sizeof(temp_str)-1,"execute(): Cannot execute external programm: '%s', Error: '%s' !\n",ext_prg,strerror(errno));
      write_log (temp_str);
      close (Pipe[0]);
      close (Pipe[1]);
      exit (253); /* Parent will get return status: 253 */
     }

    close (Pipe[1]);

   }

  
  if (rcode==-1)  /* Parent */
   {
    snprintf  (temp_str,sizeof(temp_str)-1,"execute(): 'Fork' command failed: '%s' !\n",strerror(errno));
    write_log (temp_str);
    close (Pipe[0]);
    close (Pipe[1]);
    return -1;
   }

  /* Prepare for signal processing */

  pid_to_kill=rcode;
  
  alarm (EXT_PRG_TIMEOUT);


  if (waitpid (rcode,&status, (WUNTRACED))==-1)
   {
    snprintf (temp_str,sizeof(temp_str)-1,"execute(): 'Waitpid' command failed: '%s' !\n",strerror(errno));
    write_log (temp_str);
    close (Pipe[0]);
    close (Pipe[1]);
    return -1;
   }


  /* First close the write end of the pipe */

  close (Pipe[1]);    

  memset (&data,0,sizeof(data));

  while (read(Pipe[0],data,1)>0)
  {
   if (strlen(ext_output)<(bufsize-1)) strcat (ext_output,data);
   memset (&data,0,sizeof(data));
  }

  alarm (0); /* Stop the timer */
  
  signal (SIGALRM,prev); /* Return the prev sigaction */

  if (WIFEXITED(status))
   {
    rcode=WEXITSTATUS (status);
    if (rcode==253) goto L1;
    else
    {
     close (Pipe[0]);
     return (rcode);
    }
   }

L1:
  snprintf (temp_str,sizeof(temp_str)-1,"execute(): Abnormal child termination !\n");
  write_log (temp_str);
  close (Pipe[0]);
  close (Pipe[1]);
  return -1;
}


Данный код прекрасно работает если execute() вызвать в одном процессе. Но стоит сделать fork() и вызвать execute() в childe, waitpid всегда возвращает -1 и  ECHILD.

>2. Как задан обработчик сигнала SIGCHLD? Если SIG_IGN, то Вы будете всегда
>получать ECHILD.

Никак. Я вообще нигде его не переопределяю.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "FORK()" 
Сообщение от romanSA Искать по авторуВ закладки(??) on 14-Июл-05, 02:07  (MSK)
А можно привести код, вызывающий execute()?
И зачем используется здесь waitpid()? Хватило бы просто wait()
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "FORK()" 
Сообщение от Andrei emailИскать по авторуВ закладки(??) on 14-Июл-05, 13:40  (MSK)
>А можно привести код, вызывающий execute()?
>И зачем используется здесь waitpid()? Хватило бы просто wait()


Всем спасибо. Проблема рашена. Я не увидел ;-) в собсвенном коде явное переопределение SIGCHLD.

void childhandler(int sig)      
{                              
    waitpid(-1, NULL, WNOHANG);
}                              

.....

int main ()
{
....
signal(SIGCHLD, childhandler);
....
}

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "FORK()" 
Сообщение от Vladislav emailИскать по авторуВ закладки(??) on 15-Июл-05, 22:35  (MSK)
Да, стиль написания кода паршивый... Там много чего можно не увидеть.
Советую почитать книгу - "Refactoring"... все сразу станет на свои места.
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "FORK()" 
Сообщение от dimus emailИскать по авторуВ закладки(??) on 25-Июл-05, 10:39  (MSK)
И можно порыться в исходниках inetd, так как он давно и успешно решает Вашу задачу.
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх


Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ]
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




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

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