Index: /trunk/src/kmk/main.c
===================================================================
--- /trunk/src/kmk/main.c	(revision 3478)
+++ /trunk/src/kmk/main.c	(revision 3479)
@@ -4388,7 +4388,9 @@
         {
           need_2nd_error = 1;
-          need_2nd_error_output = job_slots_used > 2
-                               && out == NULL
+          need_2nd_error_output = job_slots_used >= 2
+                               && out != NULL
                                && out != &make_sync;
+          if (need_2nd_error_output)
+            output_metered = 0;
         }
 #endif /* KMK */
@@ -4470,6 +4472,9 @@
   {
       out->dont_truncate = 0;
-      if (need_2nd_error_output)
+fprintf(stderr, "output_metered=%d\n", output_metered);
+      if (need_2nd_error_output && output_metered > 20)
         output_dump (out);
+      else
+        output_reset (out);
       output_close (out);
   }
@@ -4480,5 +4485,5 @@
 
 #ifdef KMK
-void die(int status)
+void die (int status)
 {
     die_with_job_output (status, NULL);
Index: /trunk/src/kmk/output.c
===================================================================
--- /trunk/src/kmk/output.c	(revision 3478)
+++ /trunk/src/kmk/output.c	(revision 3479)
@@ -58,4 +58,35 @@
 #else
 # define STREAM_OK(_s) 1
+#endif
+
+
+#if defined(KMK) && !defined(NO_OUTPUT_SYNC)
+/* Non-negative if we're counting output lines.
+
+   This is used by die_with_job_output to decide whether the initial build
+   error needs to be repeated because there was too much output from parallel
+   jobs between it and the actual make termination. */
+int output_metered = -1;
+
+static void meter_output_block (char const *buffer, size_t len)
+{
+  while (len > 0)
+    {
+      char *nl = (char *)memchr (buffer, '\n', len);
+      size_t linelen;
+      if (nl)
+        {
+          linelen = nl - buffer + 1;
+          output_metered++;
+        }
+      else
+          linelen = len;
+      output_metered += linelen / 132;
+
+      /* advance */
+      buffer += linelen;
+      len    -= linelen;
+    }
+}
 #endif
 
@@ -78,4 +109,40 @@
 static int combined_output = -1;
 
+/* Helper for membuf_reset and output_reset */
+static membuf_reset (struct output *out)
+{
+  struct output_segment *seg;
+  while ((seg = out->out.head_seg))
+    {
+     out->out.head_seg = seg->next;
+     free (seg);
+    }
+  out->out.tail_seg = NULL;
+  out->out.tail_run = NULL;
+  out->out.head_run = NULL;
+  out->out.left     = 0;
+  out->out.total    = 0;
+
+  while ((seg = out->err.head_seg))
+    {
+     out->err.head_seg = seg->next;
+     free (seg);
+    }
+  out->err.tail_seg = NULL;
+  out->err.tail_run = NULL;
+  out->err.head_run = NULL;
+  out->err.left     = 0;
+  out->err.total    = 0;
+
+  out->seqno = 0;
+}
+
+/* Used by die_with_job_output to suppress output when it shouldn't be repeated. */
+void output_reset (struct output *out)
+{
+  if (out && (out->out.total || out->err.total))
+    membuf_reset (out);
+}
+
 /* Internal worker for output_dump and membuf_dump_most. */
 static void membuf_dump (struct output *out)
@@ -86,5 +153,4 @@
       struct output_run *err_run;
       struct output_run *out_run;
-      struct output_segment *seg;
       FILE *prevdst;
 
@@ -130,4 +196,10 @@
             fflush(prevdst);
           prevdst = dst;
+#ifdef KMK
+          if (output_metered < 0)
+            { /* likely */ }
+          else
+            meter_output_block (src, len);
+#endif
 # if 0 /* for debugging */
           while (len > 0)
@@ -179,27 +251,5 @@
 
       /* Free the segments and reset the state. */
-      while ((seg = out->out.head_seg))
-        {
-         out->out.head_seg = seg->next;
-         free (seg);
-        }
-      out->out.tail_seg = NULL;
-      out->out.tail_run = NULL;
-      out->out.head_run = NULL;
-      out->out.left     = 0;
-      out->out.total    = 0;
-
-      while ((seg = out->err.head_seg))
-        {
-         out->err.head_seg = seg->next;
-         free (seg);
-        }
-      out->err.tail_seg = NULL;
-      out->err.tail_run = NULL;
-      out->err.head_run = NULL;
-      out->err.left     = 0;
-      out->err.total    = 0;
-
-      out->seqno = 0;
+      membuf_reset (out);
     }
   else
@@ -756,4 +806,10 @@
       if (len <= 0)
         break;
+#ifdef KMK
+      if (output_metered < 0)
+        { /* likely */ }
+      else
+        meter_output_block (buffer, len);
+#endif
       if (fwrite (buffer, len, 1, to) < 1)
         {
@@ -953,4 +1009,26 @@
 #endif
 }
+
+# if defined(KMK) && !defined(CONFIG_WITH_OUTPUT_IN_MEMORY)
+/* Used by die_with_job_output to suppress output when it shouldn't be repeated. */
+void output_reset (struct output *out)
+{
+  if (out)
+    {
+      if (out->out != OUTPUT_NONE)
+        {
+          int e;
+          lseek (out->out, 0, SEEK_SET);
+          EINTRLOOP (e, ftruncate (out->out, 0));
+        }
+      if (out->err != OUTPUT_NONE && out->err != out->out)
+        {
+          int e;
+          lseek (out->err, 0, SEEK_SET);
+          EINTRLOOP (e, ftruncate (out->err, 0));
+        }
+    }
+}
+# endif
 #endif /* NO_OUTPUT_SYNC */
 
Index: /trunk/src/kmk/output.h
===================================================================
--- /trunk/src/kmk/output.h	(revision 3478)
+++ /trunk/src/kmk/output.h	(revision 3479)
@@ -67,4 +67,7 @@
 extern struct output *output_context;
 extern unsigned int stdio_traced;
+#if defined(KMK) && !defined(NO_OUTPUT_SYNC)
+extern int output_metered;
+#endif
 
 #define OUTPUT_SET(_new)    do{ output_context = (_new)->syncout ? (_new) : NULL; }while(0)
@@ -96,4 +99,7 @@
 /* Dump any child output content to stdout, and reset it.  */
 void output_dump (struct output *out);
+# ifdef KMK
+void output_reset (struct output *out);
+# endif
 #endif
 
