* 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 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 plk malloc; xmalloc "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>
* .purify: New file: suppress some known-OK Purify messages.
* read.c (read_makefile): Remember to free the commands buffer if
we can't find a makefile.
* 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).
* 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
file descriptor and it's leaking :-/.
* getloadavg.c (getloadavg): Ditto.
1999-07-15 Paul D. Smith <psmith@gnu.org>
@ -371,9 +386,9 @@
1998-10-13 Paul D. Smith <psmith@gnu.org>
* job.c (new_job): If the command list resolves to empty (through
variable expansion, for example), stop early rather than running
start_waiting_job().
* job.c (start_job_command): If the command list resolves to no
chars at all (e.g.: "foo:;$(empty)") then command_ptr is NULL;
quit early.
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.
If we have gotten this far, all the previous commands
have run successfully, so we have winning update status. */
set_command_state (file, cs_running);
file->update_status = 0;
notice_finished_file (file);
return;

View file

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

View file

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

34
job.c
View file

@ -744,6 +744,10 @@ start_job_command (child)
char **argv;
#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
the flags specified globally for this target. */
flags = (child->file->command_flags
@ -812,14 +816,16 @@ start_job_command (child)
{
next_command:
#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
/* This line has no commands. Go to the next. */
if (job_next_command (child))
start_job_command (child);
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;
notice_finished_file (child->file);
}
@ -843,11 +849,12 @@ start_job_command (child)
#else
(argv[0] && !strcmp(argv[0], "/bin/sh"))
#endif
&& (argv[1] && !strcmp(argv[1], "-c"))
&& (argv[2] && !strcmp(argv[2], ":"))
&& (argv[1] && !strcmp(argv[1], "-c"))
&& (argv[2] && !strcmp(argv[2], ":"))
&& argv[3] == NULL)
{
set_command_state (child->file, cs_running);
free (argv[0]);
free ((char *) argv);
goto next_command;
}
#endif /* !VMS && !_AMIGA */
@ -1144,7 +1151,7 @@ start_waiting_job (c)
/* 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
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
before someone else does, or (b) a signal, such as SIGCHLD,
is caught (because we installed a handler for it). If the
@ -1364,16 +1371,11 @@ new_job (file)
c->job_token = 0;
/* Fetch the first command line to be run. */
if (job_next_command (c))
/* The job is now primed. Start it running. */
(void)start_waiting_job (c);
else
{
/* There were no commands (variable expands to empty?). All done. */
c->file->update_status = 0;
notice_finished_file(c->file);
free_child (c);
}
job_next_command (c);
/* The job is now primed. Start it running.
(This will notice if there are in fact no commands.) */
(void)start_waiting_job (c);
if (job_slots == 1)
/* 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;
struct linebuffer lb;
unsigned int commands_len = 200;
char *commands = (char *) xmalloc (200);
char *commands;
unsigned int commands_idx = 0;
unsigned int cmds_started;
char *p;
@ -396,7 +396,6 @@ read_makefile (filename, flags)
attempt, rather from FILENAME itself. Restore it in case the
caller wants to use it in a message. */
errno = makefile_errno;
free (commands);
return 0;
}
@ -408,6 +407,7 @@ read_makefile (filename, flags)
when the start of the next rule (or eof) is encountered. */
initbuffer (&lb);
commands = xmalloc (200);
while (!feof (infile))
{

13
rule.c
View file

@ -439,10 +439,23 @@ freerule (rule, lastrule)
{
struct rule *next = rule->next;
register unsigned int i;
register struct dep *dep;
for (i = 0; rule->targets[i] != 0; ++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->suffixes);
free ((char *) rule->lens);