properly handle child processes

From-SVN: r26644
This commit is contained in:
Bruce Korb 1999-04-26 10:38:38 +00:00
parent 039d4bcecc
commit d1c6a037a2
3 changed files with 188 additions and 108 deletions

View File

@ -147,9 +147,11 @@ pid_t process_chain_head = (pid_t) -1;
const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
regex_t incl_quote_re;
char *load_file (const char *pzFile);
void process (char *data, const char *file);
void run_compiles (void);
char *load_file (const char *);
void process (char *, const char *);
void run_compiles ();
void wait_for_pid( pid_t, int );
void initialize ();
#include "fixincl.x"
@ -164,8 +166,6 @@ main (argc, argv)
{
static const char gnu_lib_mark[] =
"This file is part of the GNU C Library";
static const char var_not_found[] =
"fixincl ERROR: %s environment variable not defined\n";
#ifndef NO_BOGOSITY_LIMITS
# define BOGUS_LIMIT MINIMUM_MAXIMUM_LINES
@ -212,6 +212,113 @@ main (argc, argv)
exit (EXIT_FAILURE);
}
initialize ();
#ifndef NO_BOGOSITY_LIMITS
/* Some systems only allow so many calls to fork(2).
This is inadequate for this program. Consequently,
we must let a grandfather process spawn children
that then spawn all the processes that do the real work.
*/
for (;;)
{
file_name_ct = 0;
{
char *pz_buf = file_name_buf;
/* Only the parent process can read from stdin without confusing
the world. (How does the child tell the parent to skip
forward? Pipes and files behave differently.) */
while ( (file_name_ct < BOGUS_LIMIT)
&& (pz_buf < (file_name_buf + NAME_TABLE_SIZE - MAXPATHLEN)))
{
if (fgets (pz_buf, MAXPATHLEN, stdin) == (char *) NULL)
break;
while (isspace (*pz_buf))
pz_buf++;
if ((*pz_buf == '\0') || (*pz_buf == '#'))
continue;
apz_names[file_name_ct++] = pz_buf;
pz_buf += strlen (pz_buf);
while (isspace (pz_buf[-1]))
pz_buf--;
*pz_buf++ = '\0';
}
}
/* IF we did not get any files this time thru
THEN we must be done. */
if (file_name_ct == 0)
return EXIT_SUCCESS;
{
pid_t child = fork ();
if (child == NULLPROCESS)
break;
if (child == NOPROCESS)
{
fprintf (stderr, "Error %d (%s) forking in main\n",
errno, strerror (errno));
exit (EXIT_FAILURE);
}
wait_for_pid( child, file_name_ct );
}
}
#else
#error "NON-BOGUS LIMITS NOT SUPPORTED?!?!"
#endif
/*
Here we are the child of the grandparent process. The parent
of all the little fixup processes. We ignore the deaths of
our children. */
signal (SIGCLD, SIG_IGN);
#ifdef DEBUG
fprintf (stderr, "Child start -- processing %d files\n",
file_name_ct);
#endif
/* For every file specified in stdandard in
(except as throttled for bogus reasons)...
*/
for (loop_ct = 0; loop_ct < file_name_ct; loop_ct++)
{
char *pz_data;
char *pz_file_name = apz_names[loop_ct];
if (access (pz_file_name, R_OK) != 0)
{
int erno = errno;
fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
pz_file_name, getcwd ((char *) NULL, MAXPATHLEN),
erno, strerror (erno));
}
else if (pz_data = load_file (pz_file_name), (pz_data != (char *) NULL))
{
if (strstr (pz_data, gnu_lib_mark) == (char *) NULL)
process (pz_data, pz_file_name);
free ((void *) pz_data);
}
}
return EXIT_SUCCESS;
}
/* * * * * * * * * * * * */
void
initialize()
{
static const char var_not_found[] =
"fixincl ERROR: %s environment variable not defined\n";
{
static const char var[] = "TARGET_MACHINE";
pz_machine = getenv (var);
@ -264,110 +371,74 @@ main (argc, argv)
signal (SIGALRM, SIG_IGN);
signal (SIGTERM, SIG_IGN);
#ifndef NO_BOGOSITY_LIMITS
/* Some systems only allow so many calls to fork(2).
This is inadequate for this program. Consequently,
we must let a grandfather process spawn children
that then spawn all the processes that do the real work.
*/
for (;;)
{
char *pz_buf;
pid_t child;
/*
Make sure that if we opened a server process, we close it now.
This is the grandparent process. We don't need the server anymore
and our children should make their own. */
/* Only the parent process can read from stdin without confusing
the world. (How does the child tell the parent to skip
forward? Pipes and files behave differently.) */
file_name_ct = 0;
pz_buf = file_name_buf;
while ( (file_name_ct < BOGUS_LIMIT)
&& (pz_buf < (file_name_buf + NAME_TABLE_SIZE - MAXPATHLEN)))
{
if (fgets (pz_buf, MAXPATHLEN, stdin) == (char *) NULL)
break;
while (isspace (*pz_buf))
pz_buf++;
if ((*pz_buf == '\0') || (*pz_buf == '#'))
continue;
apz_names[file_name_ct++] = pz_buf;
pz_buf += strlen (pz_buf);
while (isspace (pz_buf[-1]))
pz_buf--;
*pz_buf++ = '\0';
}
close_server ();
(void)wait ( (int*)NULL );
}
/* IF we did not get any files this time thru
THEN we must be done. */
if (file_name_ct == 0)
return EXIT_SUCCESS;
child = fork ();
if (child == NULLPROCESS)
break;
if (child == NOPROCESS)
{
fprintf (stderr, "Error %d (%s) forking in main\n",
errno, strerror (errno));
exit (EXIT_FAILURE);
}
#ifndef DEBUG
{
int status;
(void)wait (&status);
}
#else
fprintf (stderr, "Waiting for %d to complete %d files\n",
child, file_name_ct);
{
int status;
pid_t dead_kid = wait (&status);
if (dead_kid != child)
fprintf (stderr, "fixincl woke up from a strange child %d (not %d)\n",
dead_kid, child);
else
fprintf (stderr, "child finished %d files %s\n", file_name_ct,
status ? strerror (status & 0xFF) : "ok");
}
#endif
}
#else
#error "NON-BOGUS LIMITS NOT SUPPORTED?!?!"
#endif
signal (SIGCLD, SIG_IGN);
/* * * * * * * * * * * * *
wait_for_pid - Keep calling `wait(2)' until it returns
the process id we are looking for. Not every system has
`waitpid(2)'. We also ensure that the children exit with success. */
void
wait_for_pid( pid_t child, int file_name_ct )
{
#ifdef DEBUG
fprintf (stderr, "Child start -- processing %d files\n",
file_name_ct);
fprintf (stderr, "Waiting for %d to complete %d files\n",
child, file_name_ct);
#endif
/* For every file specified in stdandard in
(except as throttled for bogus reasons)...
*/
for (loop_ct = 0; loop_ct < file_name_ct; loop_ct++)
{
char *pz_data;
char *pz_file_name = apz_names[loop_ct];
for (;;) {
int status;
pid_t dead_kid = wait (&status);
if (access (pz_file_name, R_OK) != 0)
{
int erno = errno;
fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
pz_file_name, getcwd ((char *) NULL, MAXPATHLEN),
erno, strerror (erno));
}
else if (pz_data = load_file (pz_file_name), (pz_data != (char *) NULL))
{
if (strstr (pz_data, gnu_lib_mark) == (char *) NULL)
process (pz_data, pz_file_name);
free ((void *) pz_data);
}
}
if (dead_kid == child)
{
if (! WIFEXITED( status ))
{
fprintf (stderr, "child process %d is hung on signal %d\n",
child, WSTOPSIG( status ));
exit (EXIT_FAILURE);
}
if (WEXITSTATUS( status ) != 0)
{
fprintf (stderr, "child process %d exited with status %d\n",
child, WEXITSTATUS( status ));
exit (EXIT_FAILURE);
}
#ifdef DEBUG
fprintf (stderr, "child finished %d files %s\n", file_name_ct,
status ? strerror (status & 0xFF) : "ok");
#endif
break; /* normal child completion */
}
return EXIT_SUCCESS;
/*
IF there is an error, THEN see if it is retryable.
If it is not retryable, then break out of this loop. */
if (dead_kid == NOPROCESS)
{
switch (errno) {
case EINTR:
case EAGAIN:
break;
default:
fprintf (stderr, "Error %d (%s) waiting for %d to finish\n",
errno, strerror( errno ), child );
/* FALLTHROUGH */
case ECHILD: /* no children to wait for?? */
return;
}
}
} done_waiting:;
}
@ -476,6 +547,12 @@ run_compiles ()
exit (EXIT_FAILURE);
}
/* Make sure re_compile_pattern does not stumble across invalid
data */
memset ( (void*)p_re, '\0', REGEX_COUNT * sizeof (regex_t) );
memset ( (void*)&incl_quote_re, '\0', sizeof (regex_t) );
/* The patterns we search for are all egrep patterns.
In the shell version of this program, we invoke egrep
with the supplied pattern. Here, we will run

View File

@ -178,14 +178,17 @@ load_data (fp)
* Make certain the server process is dead, close the
* pipes to it and from it, finally NULL out the file pointers
*/
static void
void
close_server ()
{
kill ((pid_t) server_id, SIGKILL);
server_id = NULLPROCESS;
fclose (server_pair.pf_read);
fclose (server_pair.pf_write);
server_pair.pf_read = server_pair.pf_write = (FILE *) NULL;
if (server_id != NULLPROCESS)
{
kill ((pid_t) server_id, SIGKILL);
server_id = NULLPROCESS;
fclose (server_pair.pf_read);
fclose (server_pair.pf_write);
server_pair.pf_read = server_pair.pf_write = (FILE *) NULL;
}
}
/*

View File

@ -90,5 +90,5 @@ pid_t proc2_open _P_ (( t_fd_pair * p_pair, t_pchar * pp_args));
int chain_open _P_ (( int in_fd,
t_pchar * pp_args,
pid_t * p_child));
void close_server _P_ (( void ));
#endif /* FIXINC_SERVER_H */