* Fix memory leaks, fd leaks, and some long-standing bugs recognizing when
authorPaul Smith <psmith@gnu.org>
Tue, 20 Jul 1999 22:34:41 +0000 (22:34 +0000)
committerPaul Smith <psmith@gnu.org>
Tue, 20 Jul 1999 22:34:41 +0000 (22:34 +0000)
  targets need to have their modtimes rechecked (-n, etc.)

.purify
ChangeLog
commands.c
getloadavg.c
implicit.c
job.c
read.c
rule.c

diff --git a/.purify b/.purify
index 098e741..dc1b1d9 100644 (file)
--- 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"
index 3895a85..6e22e4c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,28 @@
-1999-07-16  Paul D. Smith  <psmith@gnu.org>
+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.
 
-       * .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  <psmith@gnu.org>
 
-       * 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>
 
 
 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>
 
index dd7b1be..9d7a5de 100644 (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;
index 36245ef..79eedfc 100644 (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
index dfe19da..3ed23a3 100644 (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])
diff --git a/job.c b/job.c
index e84897b..0ae2d74 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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);