Commit d1c6a037 by Bruce Korb

properly handle child processes

From-SVN: r26644
parent 039d4bce
......@@ -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,57 +212,7 @@ main (argc, argv)
exit (EXIT_FAILURE);
}
{
static const char var[] = "TARGET_MACHINE";
pz_machine = getenv (var);
if (pz_machine == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
}
{
static const char var[] = "DESTDIR";
pz_dest_dir = getenv (var);
if (pz_dest_dir == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
}
{
static const char var[] = "SRCDIR";
pz_src_dir = getenv (var);
if (pz_src_dir == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
}
{
static const char var[] = "FIND_BASE";
pz_find_base = getenv (var);
if (pz_find_base == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
find_base_len = strlen( pz_find_base );
}
/* Compile all the regular expressions now.
That way, it is done only once for the whole run.
*/
run_compiles ();
signal (SIGQUIT, SIG_IGN);
signal (SIGIOT, SIG_IGN);
signal (SIGPIPE, SIG_IGN);
signal (SIGALRM, SIG_IGN);
signal (SIGTERM, SIG_IGN);
initialize ();
#ifndef NO_BOGOSITY_LIMITS
/* Some systems only allow so many calls to fork(2).
......@@ -272,14 +222,15 @@ main (argc, argv)
*/
for (;;)
{
char *pz_buf;
pid_t child;
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.) */
file_name_ct = 0;
pz_buf = file_name_buf;
while ( (file_name_ct < BOGUS_LIMIT)
&& (pz_buf < (file_name_buf + NAME_TABLE_SIZE - MAXPATHLEN)))
{
......@@ -295,13 +246,15 @@ main (argc, argv)
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;
child = fork ();
{
pid_t child = fork ();
if (child == NULLPROCESS)
break;
......@@ -311,32 +264,19 @@ main (argc, argv)
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");
wait_for_pid( child, file_name_ct );
}
#endif
}
#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
......@@ -371,6 +311,137 @@ main (argc, argv)
}
/* * * * * * * * * * * * */
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);
if (pz_machine == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
}
{
static const char var[] = "DESTDIR";
pz_dest_dir = getenv (var);
if (pz_dest_dir == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
}
{
static const char var[] = "SRCDIR";
pz_src_dir = getenv (var);
if (pz_src_dir == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
}
{
static const char var[] = "FIND_BASE";
pz_find_base = getenv (var);
if (pz_find_base == (char *) NULL)
{
fprintf (stderr, var_not_found, var);
exit (EXIT_FAILURE);
}
find_base_len = strlen( pz_find_base );
}
/* Compile all the regular expressions now.
That way, it is done only once for the whole run.
*/
run_compiles ();
signal (SIGQUIT, SIG_IGN);
signal (SIGIOT, SIG_IGN);
signal (SIGPIPE, SIG_IGN);
signal (SIGALRM, SIG_IGN);
signal (SIGTERM, SIG_IGN);
/*
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. */
close_server ();
(void)wait ( (int*)NULL );
}
/* * * * * * * * * * * * *
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, "Waiting for %d to complete %d files\n",
child, file_name_ct);
#endif
for (;;) {
int status;
pid_t dead_kid = wait (&status);
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 */
}
/*
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:;
}
/* * * * * * * * * * * * *
load_file loads all the contents of a file into malloc-ed memory.
......@@ -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
......
......@@ -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 ()
{
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;
}
}
/*
......
......@@ -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 */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment