* Fix memory leaks, fd leaks, and some long-standing bugs recognizing when

targets need to have their modtimes rechecked (-n, etc.)
This commit is contained in:
Paul Smith 1999-07-20 22:34:41 +00:00
parent 169e6b8c3d
commit 73846549f6
8 changed files with 70 additions and 29 deletions

View file

@ -1,4 +1,11 @@
# Solaris (2.5.1) has a couple if issues.
#
suppress plk malloc; setvbuf "libc*"; main "main.c" suppress plk malloc; setvbuf "libc*"; main "main.c"
suppress umr kstat_read; kstat_chain_update; kstat_open; getloadavg
suppress umr kstat_chain_update; kstat_open; getloadavg
# The command line options stuff leaks a little bit. No big deal.
#
suppress mlk malloc; xmalloc "misc.c"; decode_env_switches "main.c" suppress mlk malloc; xmalloc "misc.c"; decode_env_switches "main.c"
suppress plk malloc; xmalloc "misc.c"; decode_env_switches "main.c" suppress plk malloc; xmalloc "misc.c"; decode_env_switches "main.c"
suppress mlk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c" suppress mlk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c"

View file

@ -1,13 +1,28 @@
1999-07-20 Paul D. Smith <psmith@gnu.org>
* job.c (start_job_command): Ensure that the state of the target
is cs_running. It might not be if we skipped all the lines due to
-n (for example).
* commands.c (execute_file_commands): If we discover that the
command script is empty and succeed early, set cs_running so the
modtime of the target is still rechecked.
* rule.c (freerule): Free the dependency list for the rule.
* implicit.c (pattern_search): When turning an intermediate file
into a real target, keep the also_make list.
Free the dep->name if we didn't use it during enter_file().
1999-07-16 Paul D. Smith <psmith@gnu.org> 1999-07-16 Paul D. Smith <psmith@gnu.org>
* .purify: New file: suppress some known-OK Purify messages. * read.c (read_makefile): Don't allocate the commands buffer until
we're sure we found a makefile and won't return early (mem leak).
* read.c (read_makefile): Remember to free the commands buffer if
we can't find a makefile.
* job.c (start_job_command): Broken #ifdef test: look for F_SETFD, * job.c (start_job_command): Broken #ifdef test: look for F_SETFD,
not FD_SETFD. Close-on-exec isn't getting set on the bad_stdin not FD_SETFD. Close-on-exec isn't getting set on the bad_stdin
file descriptor and it's leaking :-/. file descriptor and it's leaking :-/.
* getloadavg.c (getloadavg): Ditto.
1999-07-15 Paul D. Smith <psmith@gnu.org> 1999-07-15 Paul D. Smith <psmith@gnu.org>
@ -371,9 +386,9 @@
1998-10-13 Paul D. Smith <psmith@gnu.org> 1998-10-13 Paul D. Smith <psmith@gnu.org>
* job.c (new_job): If the command list resolves to empty (through * job.c (start_job_command): If the command list resolves to no
variable expansion, for example), stop early rather than running chars at all (e.g.: "foo:;$(empty)") then command_ptr is NULL;
start_waiting_job(). quit early.
1998-10-12 Andreas Schwab <schwab@issan.cs.uni-dortmund.de> 1998-10-12 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>

View file

@ -344,6 +344,7 @@ execute_file_commands (file)
/* We are all out of commands. /* We are all out of commands.
If we have gotten this far, all the previous commands If we have gotten this far, all the previous commands
have run successfully, so we have winning update status. */ have run successfully, so we have winning update status. */
set_command_state (file, cs_running);
file->update_status = 0; file->update_status = 0;
notice_finished_file (file); notice_finished_file (file);
return; return;

View file

@ -966,7 +966,7 @@ getloadavg (loadavg, nelem)
{ {
/* Set the channel to close on exec, so it does not /* Set the channel to close on exec, so it does not
litter any child's descriptor table. */ litter any child's descriptor table. */
# ifdef FD_SETFD # ifdef F_SETFD
# ifndef FD_CLOEXEC # ifndef FD_CLOEXEC
# define FD_CLOEXEC 1 # define FD_CLOEXEC 1
# endif # endif

View file

@ -524,6 +524,7 @@ pattern_search (file, archive, depth, recursions)
f->deps = imf->deps; f->deps = imf->deps;
f->cmds = imf->cmds; f->cmds = imf->cmds;
f->stem = imf->stem; f->stem = imf->stem;
f->also_make = imf->also_make;
imf = lookup_file (intermediate_patterns[deps_found]); imf = lookup_file (intermediate_patterns[deps_found]);
if (imf != 0 && imf->precious) if (imf != 0 && imf->precious)
f->precious = 1; f->precious = 1;
@ -532,6 +533,9 @@ pattern_search (file, archive, depth, recursions)
for (dep = f->deps; dep != 0; dep = dep->next) for (dep = f->deps; dep != 0; dep = dep->next)
{ {
dep->file = enter_file (dep->name); dep->file = enter_file (dep->name);
/* enter_file uses dep->name _if_ we created a new file. */
if (dep->name != dep->file->name)
free (dep->name);
dep->name = 0; dep->name = 0;
dep->file->tried_implicit |= dep->changed; dep->file->tried_implicit |= dep->changed;
} }
@ -591,10 +595,9 @@ pattern_search (file, archive, depth, recursions)
file->cmds = rule->cmds; file->cmds = rule->cmds;
/* Put the targets other than the one that /* If this rule builds other targets, too, put the others into FILE's
matched into FILE's `also_make' member. */ `also_make' member. */
/* If there was only one target, there is nothing to do. */
if (rule->targets[1] != 0) if (rule->targets[1] != 0)
for (i = 0; rule->targets[i] != 0; ++i) for (i = 0; rule->targets[i] != 0; ++i)
if (i != matches[foundrule]) if (i != matches[foundrule])

34
job.c
View file

@ -744,6 +744,10 @@ start_job_command (child)
char **argv; char **argv;
#endif #endif
/* If we have a completely empty commandset, stop now. */
if (!child->command_ptr)
goto next_command;
/* Combine the flags parsed for the line itself with /* Combine the flags parsed for the line itself with
the flags specified globally for this target. */ the flags specified globally for this target. */
flags = (child->file->command_flags flags = (child->file->command_flags
@ -812,14 +816,16 @@ start_job_command (child)
{ {
next_command: next_command:
#ifdef __MSDOS__ #ifdef __MSDOS__
execute_by_shell = 0; /* in case construct_command_argv sets it */ execute_by_shell = 0; /* in case construct_command_argv sets it */
#endif #endif
/* This line has no commands. Go to the next. */ /* This line has no commands. Go to the next. */
if (job_next_command (child)) if (job_next_command (child))
start_job_command (child); start_job_command (child);
else else
{ {
/* No more commands. All done. */ /* No more commands. Make sure we're "running"; we might not be if
(e.g.) all commands were skipped due to -n. */
set_command_state (child->file, cs_running);
child->file->update_status = 0; child->file->update_status = 0;
notice_finished_file (child->file); notice_finished_file (child->file);
} }
@ -843,11 +849,12 @@ start_job_command (child)
#else #else
(argv[0] && !strcmp(argv[0], "/bin/sh")) (argv[0] && !strcmp(argv[0], "/bin/sh"))
#endif #endif
&& (argv[1] && !strcmp(argv[1], "-c")) && (argv[1] && !strcmp(argv[1], "-c"))
&& (argv[2] && !strcmp(argv[2], ":")) && (argv[2] && !strcmp(argv[2], ":"))
&& argv[3] == NULL) && argv[3] == NULL)
{ {
set_command_state (child->file, cs_running); free (argv[0]);
free ((char *) argv);
goto next_command; goto next_command;
} }
#endif /* !VMS && !_AMIGA */ #endif /* !VMS && !_AMIGA */
@ -1144,7 +1151,7 @@ start_waiting_job (c)
/* Read a token. We set the non-blocking bit on this earlier, /* Read a token. We set the non-blocking bit on this earlier,
so if there's no token to be read we'll fall through to the so if there's no token to be read we'll fall through to the
select. The select block until (a) there's data to read, select. The select blocks until (a) there's data to read,
in which case we come back around and try to grab the token in which case we come back around and try to grab the token
before someone else does, or (b) a signal, such as SIGCHLD, before someone else does, or (b) a signal, such as SIGCHLD,
is caught (because we installed a handler for it). If the is caught (because we installed a handler for it). If the
@ -1364,16 +1371,11 @@ new_job (file)
c->job_token = 0; c->job_token = 0;
/* Fetch the first command line to be run. */ /* Fetch the first command line to be run. */
if (job_next_command (c)) job_next_command (c);
/* The job is now primed. Start it running. */
(void)start_waiting_job (c); /* The job is now primed. Start it running.
else (This will notice if there are in fact no commands.) */
{ (void)start_waiting_job (c);
/* There were no commands (variable expands to empty?). All done. */
c->file->update_status = 0;
notice_finished_file(c->file);
free_child (c);
}
if (job_slots == 1) if (job_slots == 1)
/* Since there is only one job slot, make things run linearly. /* Since there is only one job slot, make things run linearly.

4
read.c
View file

@ -280,7 +280,7 @@ read_makefile (filename, flags)
register FILE *infile; register FILE *infile;
struct linebuffer lb; struct linebuffer lb;
unsigned int commands_len = 200; unsigned int commands_len = 200;
char *commands = (char *) xmalloc (200); char *commands;
unsigned int commands_idx = 0; unsigned int commands_idx = 0;
unsigned int cmds_started; unsigned int cmds_started;
char *p; char *p;
@ -396,7 +396,6 @@ read_makefile (filename, flags)
attempt, rather from FILENAME itself. Restore it in case the attempt, rather from FILENAME itself. Restore it in case the
caller wants to use it in a message. */ caller wants to use it in a message. */
errno = makefile_errno; errno = makefile_errno;
free (commands);
return 0; return 0;
} }
@ -408,6 +407,7 @@ read_makefile (filename, flags)
when the start of the next rule (or eof) is encountered. */ when the start of the next rule (or eof) is encountered. */
initbuffer (&lb); initbuffer (&lb);
commands = xmalloc (200);
while (!feof (infile)) while (!feof (infile))
{ {

13
rule.c
View file

@ -439,10 +439,23 @@ freerule (rule, lastrule)
{ {
struct rule *next = rule->next; struct rule *next = rule->next;
register unsigned int i; register unsigned int i;
register struct dep *dep;
for (i = 0; rule->targets[i] != 0; ++i) for (i = 0; rule->targets[i] != 0; ++i)
free (rule->targets[i]); free (rule->targets[i]);
dep = rule->deps;
while (dep)
{
struct dep *t;
t = dep->next;
/* We might leak dep->name here, but I'm not sure how to fix this: I
think that pointer might be shared (e.g., in the file hash?) */
free ((char *) dep);
dep = t;
}
free ((char *) rule->targets); free ((char *) rule->targets);
free ((char *) rule->suffixes); free ((char *) rule->suffixes);
free ((char *) rule->lens); free ((char *) rule->lens);