* Start rewrite of jobserver to avoid unique tokens for debugging.

This commit is contained in:
Paul Smith 1999-08-23 05:35:14 +00:00
parent 6fa76a7d15
commit b3fa4b3c7e
2 changed files with 116 additions and 166 deletions

118
job.c
View File

@ -202,11 +202,6 @@ unsigned int job_slots_used = 0;
static int good_stdin_used = 0;
/* Specifies whether the current process's reserved job token is in use.
'+' means it's available, '-' means it isn't. */
static char my_job_token = '+';
/* Chain of children waiting to run until the load average goes down. */
static struct child *waiting_jobs = 0;
@ -224,42 +219,11 @@ int unixy_shell = 1;
*/
int w32_kill(int pid, int sig)
{
return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
}
#endif /* WINDOWS32 */
static void
free_job_token (child)
struct child *child;
{
switch (child->job_token)
{
case '-':
/* If this child doesn't have a token, punt. */
return;
case '+':
/* If this child has the reserved token, take it back. */
my_job_token = '+';
break;
default:
/* Write any other job tokens back to the pipe. */
while (write (job_fds[1], &child->job_token, 1) != 1)
if (!EINTR_SET)
pfatal_with_name (_("write jobserver"));
break;
}
if (debug_flag)
printf (_("Released token `%c' for child 0x%08lx (%s).\n"),
child->job_token, (unsigned long int) child, child->file->name);
child->job_token = '-';
}
/* Write an error message describing the exit status given in
EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
Append "(ignored)" if IGNORED is nonzero. */
@ -419,10 +383,9 @@ reap_children (block, err)
any_remote |= c->remote;
any_local |= ! c->remote;
if (debug_flag)
printf (_("Live child 0x%08lx (%s) PID %ld token %c%s\n"),
printf (_("Live child 0x%08lx (%s) PID %ld %s\n"),
(unsigned long int) c, c->file->name,
(long) c->pid, c->job_token,
c->remote ? _(" (remote)") : "");
(long) c->pid, c->remote ? _(" (remote)") : "");
#ifdef VMS
break;
#endif
@ -580,9 +543,9 @@ reap_children (block, err)
continue;
if (debug_flag)
printf (_("Reaping %s child 0x%08lx PID %ld token %c%s\n"),
printf (_("Reaping %s child 0x%08lx PID %ld %s\n"),
child_failed ? _("losing") : _("winning"),
(unsigned long int) c, (long) c->pid, c->job_token,
(unsigned long int) c, (long) c->pid,
c->remote ? _(" (remote)") : "");
if (c->sh_batch_file) {
@ -680,8 +643,8 @@ reap_children (block, err)
notice_finished_file (c->file);
if (debug_flag)
printf (_("Removing child 0x%08lx PID %ld token %c%s from chain.\n"),
(unsigned long int) c, (long) c->pid, c->job_token,
printf (_("Removing child 0x%08lx PID %ld %s from chain.\n"),
(unsigned long int) c, (long) c->pid,
c->remote ? _(" (remote)") : "");
/* Block fatal signals while frobnicating the list, so that
@ -691,9 +654,6 @@ reap_children (block, err)
live and call reap_children again. */
block_sigs ();
/* If this job has a token out, return it. */
free_job_token (c);
/* There is now another slot open. */
if (job_slots_used > 0)
--job_slots_used;
@ -703,8 +663,8 @@ reap_children (block, err)
children = c->next;
else
lastc->next = c->next;
if (! handling_fatal_signal) /* Don't bother if about to die. */
free_child (c);
free_child (c);
unblock_sigs ();
@ -730,6 +690,27 @@ static void
free_child (child)
register struct child *child;
{
/* If this child is the only one it was our "free" job, so don't put a
token back for it. */
if (job_fds[1] >= 0 && (child != children || child->next != 0))
{
char *token = '+';
/* Write a job token back to the pipe. */
while (write (job_fds[1], &token, 1) != 1)
if (!EINTR_SET)
pfatal_with_name (_("write jobserver"));
if (debug_flag)
printf (_("Released token for child 0x%08lx (%s).\n"),
(unsigned long int) child, child->file->name);
}
if (handling_fatal_signal) /* Don't bother free'ing if about to die. */
return;
if (child->command_lines != 0)
{
register unsigned int i;
@ -746,11 +727,6 @@ free_child (child)
free ((char *) child->environment);
}
/* If this child has a token it hasn't relinquished, give it up now.
This can happen if the job completes immediately, mainly because
all the command lines evaluated to empty strings. */
free_job_token (child);
free ((char *) child);
}
@ -1220,10 +1196,9 @@ start_waiting_job (c)
case cs_running:
c->next = children;
if (debug_flag)
printf (_("Putting child 0x%08lx (%s) PID %ld token %c%s on the chain.\n"),
printf (_("Putting child 0x%08lx (%s) PID %ld%s on the chain.\n"),
(unsigned long int) c, c->file->name,
(long) c->pid, c->job_token,
c->remote ? _(" (remote)") : "");
(long) c->pid, c->remote ? _(" (remote)") : "");
children = c;
/* One more job slot is in use. */
++job_slots_used;
@ -1380,7 +1355,6 @@ new_job (file)
c->command_ptr = 0;
c->environment = 0;
c->sh_batch_file = NULL;
c->job_token = '-';
/* Fetch the first command line to be run. */
job_next_command (c);
@ -1390,22 +1364,26 @@ new_job (file)
if (job_slots != 0)
while (job_slots_used == job_slots)
reap_children (1, 0);
#ifdef MAKE_JOBSERVER
/* If we are controlling multiple jobs, and we don't yet have one,
obtain a token before starting the child. */
/* If we are controlling multiple jobs make sure we have a token before
starting the child. */
else if (job_fds[0] >= 0)
if (children == 0)
{
while (c->job_token == '-')
/* If the reserved token is available, just use that. */
if (my_job_token == '+')
{
c->job_token = my_job_token;
my_job_token = '-';
}
char token = '-';
while (token == '-')
/* If we don't already have a job started, use our "free" token. */
if (children == 0)
token = '+';
/* Read a token. As long as there's no token available we'll block.
If we get a SIGCHLD we'll return with EINTR. If one happened
before we got here we'll return immediately with EBADF because
the signal handler closes the dup'd file descriptor. */
else if (read (job_rfd, &c->job_token, 1) < 1)
{
if (errno != EINTR && errno != EBADF)
@ -1423,14 +1401,14 @@ new_job (file)
assert (c->job_token != '-');
if (debug_flag)
printf (_("Obtained token `%c' for child 0x%08lx (%s).\n"),
c->job_token, (unsigned long int) c, c->file->name);
printf (_("Obtained token for child 0x%08lx (%s).\n"),
(unsigned long int) c, c->file->name);
}
#endif
/* The job is now primed. Start it running.
(This will notice if there are in fact no commands.) */
(void)start_waiting_job (c);
(void) start_waiting_job (c);
if (job_slots == 1)
/* Since there is only one job slot, make things run linearly.

164
main.c
View File

@ -86,7 +86,6 @@ struct command_switch
flag, /* Turn int flag on. */
flag_off, /* Turn int flag off. */
string, /* One string per switch. */
int_string, /* One string. */
positive_int, /* A positive integer. */
floating, /* A floating-point number (double). */
ignore /* Ignored. */
@ -104,6 +103,7 @@ struct command_switch
char *long_name; /* Long option name. */
char *argdesc; /* Descriptive word for argument. */
char *description; /* Description for usage message. */
/* 0 means internal; don't display help. */
};
@ -195,15 +195,14 @@ static struct stringlist *makefiles = 0;
unsigned int job_slots = 1;
unsigned int default_job_slots = 1;
static char *job_slots_str = "1";
#ifndef MAKE_JOBSERVER
/* Value of job_slots that means no limit. */
static unsigned int inf_jobs = 0;
#endif
/* File descriptors for the jobs pipe. */
static struct stringlist *jobserver_fds = 0;
int job_fds[2] = { -1, -1 };
int job_rfd = -1;
@ -278,14 +277,13 @@ static const struct command_switch switches[] =
"include-dir", _("DIRECTORY"),
_("Search DIRECTORY for included makefiles") },
{ 'j',
#ifndef MAKE_JOBSERVER
positive_int, (char *) &job_slots, 1, 1, 0,
(char *) &inf_jobs, (char *) &default_job_slots,
#else
int_string, (char *)&job_slots_str, 1, 1, 0, "0", "1",
#endif
"jobs", "N",
_("Allow N jobs at once; infinite jobs with no arg") },
{ 2, string, (char *) &jobserver_fds, 1, 1, 0, 0, 0,
"jobserver-fds", 0,
0 },
{ 'k', flag, (char *) &keep_going_flag, 1, 1, 0,
0, (char *) &default_keep_going_flag,
"keep-going", 0,
@ -338,13 +336,13 @@ static const struct command_switch switches[] =
{ 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0,
"print-directory", 0,
_("Print the current directory") },
{ 2, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
{ 3, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
"no-print-directory", 0,
_("Turn off -w, even if it was turned on implicitly") },
{ 'W', string, (char *) &new_files, 0, 0, 0, 0, 0,
"what-if", _("FILE"),
_("Consider FILE to be infinitely new") },
{ 3, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
{ 4, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
"warn-undefined-variables", 0,
_("Warn when an undefined variable is referenced") },
{ '\0', }
@ -1297,52 +1295,58 @@ int main (int argc, char ** argv)
#endif
#ifdef MAKE_JOBSERVER
/* If extended jobs are available then the -j option can have one of 4
formats: (1) not specified: default is "1"; (2) specified with no value:
default is "0" (infinite); (3) specified with a single value: this means
the user wants N job slots; or (4) specified with 2 values separated by
a comma. The latter means we're a submake; the two values are the read
and write FDs, respectively, for the pipe. Note this last form is
undocumented for the user! */
/* If the jobserver-fds option is seen, make sure that -j is reasonable. */
sscanf (job_slots_str, "%d", &job_slots);
if (jobserver_fds)
{
char *cp = index (job_slots_str, ',');
char *cp;
/* In case #4, get the FDs. */
if (cp && sscanf (cp+1, "%d", &job_fds[1]) == 1)
if (jobserver_fds->max > 1)
fatal (NILF, _("internal error: multiple --jobserver-fds options."));
if (job_slots > 0)
fatal (NILF, _("internal error: --jobserver-fds unexpected."));
/* Now parse the fds string and make sure it has the proper format. */
cp = jobserver_fds->list[0];
if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
fatal (NILF,
_("internal error: invalid --jobserver-fds string `%s'."), cp);
/* Set job_slots to 0. The combination of a pipe + !job_slots means
we're using the jobserver. If !job_slots and we don't have a pipe, we
can start infinite jobs. */
job_slots = 0;
/* Create a duplicate pipe, that will be closed in the SIGCHLD
handler. If this fails with EBADF, the parent has closed the pipe
on us because it didn't think we were a submake. If so, print a
warning then default to -j1. */
if ((job_rfd = dup (job_fds[0])) < 0)
{
/* Set up the first FD and set job_slots to 0. The combination of a
pipe + !job_slots means we're using the jobserver. If !job_slots
and we don't have a pipe, we can start infinite jobs. */
job_fds[0] = job_slots;
job_slots = 0;
if (errno != EBADF)
pfatal_with_name (_("dup jobserver"));
/* Create a duplicate pipe, that will be closed in the SIGCHLD
handler. If this fails with EBADF, the parent has closed the pipe
on us because it didn't think we were a submake. If so, print a
warning then default to -j1. */
if ((job_rfd = dup (job_fds[0])) < 0)
{
if (errno != EBADF)
pfatal_with_name (_("dup jobserver"));
error (NILF,
_("warning: jobserver unavailable (using -j1). Add `+' to parent make rule."));
job_slots = 1;
job_fds[0] = job_fds[1] = -1;
job_slots_str = "1";
}
error (NILF,
_("warning: jobserver unavailable (using -j1). Add `+' to parent make rule."));
job_slots = 1;
job_fds[0] = job_fds[1] = -1;
free (jobserver_fds->list);
free (jobserver_fds);
jobserver_fds = 0;
}
}
/* In case #3 above, set up the pipe and set up the submake options
properly. */
/* If we have >1 slot but no jobserver-fds, then we're a top-level make.
Set up the pipe and install the fds option for our children. */
if (job_slots > 1)
else if (job_slots > 1)
{
char buf[(sizeof ("1024")*2)+1];
char c = '0';
char c = '+';
if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
pfatal_with_name (_("creating jobs pipe"));
@ -1351,23 +1355,21 @@ int main (int argc, char ** argv)
submakes it's the token they were given by their parent. For the
top make, we just subtract one from the number the user wants. */
job_slots = 1; /* !!!!!DEBUG!!!!! */
while (--job_slots)
{
write (job_fds[1], &c, 1);
if (c == '9')
c = 'a';
else if (c == 'z')
c = 'A';
else if (c == 'Z')
c = '0'; /* Start over again!! */
else
++c;
}
while (write (job_fds[1], &c, 1) != 1)
if (!EINTR_SET)
pfatal_with_name (_("init jobserver pipe"));
sprintf (buf, "%d,%d", job_fds[0], job_fds[1]);
job_slots_str = xstrdup (buf);
/* Fill in the jobserver_fds struct for our children. */
jobserver_fds = (struct stringlist *)
xmalloc (sizeof (struct stringlist));
jobserver_fds->list = (char **) xmalloc (sizeof (char *));
jobserver_fds->list[0] = xmalloc ((sizeof ("1024")*2)+1);
sprintf (jobserver_fds->list[0], "%d,%d", job_fds[0], job_fds[1]);
jobserver_fds->idx = 1;
jobserver_fds->max = 1;
}
#endif
@ -1790,7 +1792,6 @@ init_switches ()
long_options[i].has_arg = no_argument;
break;
case int_string:
case string:
case positive_int:
case floating:
@ -1904,7 +1905,7 @@ print_usage (bad)
{
char buf[1024], shortarg[50], longarg[50], *p;
if (cs->description[0] == '-')
if (!cs->description || cs->description[0] == '-')
continue;
switch (long_options[cs - switches].has_arg)
@ -1949,8 +1950,9 @@ print_usage (bad)
{
const struct command_switch *ncs = cs;
while ((++ncs)->c != '\0')
if (ncs->description[0] == '-' &&
ncs->description[1] == cs->c)
if (ncs->description
&& ncs->description[0] == '-'
&& ncs->description[1] == cs->c)
{
/* This is another switch that does the same
one as the one we are processing. We want
@ -2044,20 +2046,6 @@ decode_switches (argc, argv, env)
*(int *) cs->value_ptr = cs->type == flag;
break;
case int_string:
if (optarg == 0 && argc > optind
&& isdigit (argv[optind][0]))
optarg = argv[optind++];
if (!doit)
break;
if (optarg == 0)
optarg = cs->noarg_value;
*(char **) cs->value_ptr = optarg;
break;
case string:
if (!doit)
break;
@ -2356,22 +2344,6 @@ define_makeflags (all, makefile)
break;
#endif
case int_string:
if (all)
{
char *vp = *(char **) cs->value_ptr;
if (cs->default_value != 0
&& streq (vp, cs->default_value))
break;
if (cs->noarg_value != 0
&& streq (vp, cs->noarg_value))
ADD_FLAG ("", 0); /* Optional value omitted; see below. */
else
ADD_FLAG (vp, strlen (vp));
}
break;
case string:
if (all)
{