>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.
Никак. Я вообще нигде его не переопределяю.