From 73846549f62b832ca6ff761ad3640a86d3b32c86 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Tue, 20 Jul 1999 22:34:41 +0000 Subject: [PATCH] * Fix memory leaks, fd leaks, and some long-standing bugs recognizing when targets need to have their modtimes rechecked (-n, etc.) --- .purify | 7 +++++++ ChangeLog | 29 ++++++++++++++++++++++------- commands.c | 1 + getloadavg.c | 2 +- implicit.c | 9 ++++++--- job.c | 34 ++++++++++++++++++---------------- read.c | 4 ++-- rule.c | 13 +++++++++++++ 8 files changed, 70 insertions(+), 29 deletions(-) diff --git a/.purify b/.purify index 098e741..dc1b1d9 100644 --- a/.purify +++ b/.purify @@ -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" diff --git a/ChangeLog b/ChangeLog index 3895a85..6e22e4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,13 +1,28 @@ -1999-07-16 Paul D. Smith +1999-07-20 Paul D. Smith + + * 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. - * .purify: New file: suppress some known-OK Purify messages. + * 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 - * 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 @@ -371,9 +386,9 @@ 1998-10-13 Paul D. Smith - * 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 diff --git a/commands.c b/commands.c index dd7b1be..9d7a5de 100644 --- a/commands.c +++ b/commands.c @@ -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; diff --git a/getloadavg.c b/getloadavg.c index 36245ef..79eedfc 100644 --- a/getloadavg.c +++ b/getloadavg.c @@ -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 diff --git a/implicit.c b/implicit.c index dfe19da..3ed23a3 100644 --- a/implicit.c +++ b/implicit.c @@ -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]) diff --git a/job.c b/job.c index e84897b..0ae2d74 100644 --- a/job.c +++ b/job.c @@ -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. diff --git a/read.c b/read.c index 0a39ef6..bfc247e 100644 --- a/read.c +++ b/read.c @@ -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)) { diff --git a/rule.c b/rule.c index 08ab640..b813fa0 100644 --- a/rule.c +++ b/rule.c @@ -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); -- 2.7.4