diff --git a/src/main.c b/src/main.c
index d16d17a..f2910a0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -264,8 +264,7 @@ static const int inf_jobs = 0;
 
 static char *jobserver_auth = NULL;
 
-/* Handle for the mutex used on Windows to synchronize output of our
-   children under -O.  */
+/* Handle for the mutex to synchronize output of our children under -O.  */
 
 char *sync_mutex = NULL;
 
@@ -813,8 +812,6 @@ decode_output_sync_flags (void)
 #endif
 }
 
-#ifdef WINDOWS32
-
 #ifndef NO_OUTPUT_SYNC
 
 /* This is called from start_job_command when it detects that
@@ -828,14 +825,21 @@ prepare_mutex_handle_string (sync_handle_t handle)
     {
       /* Prepare the mutex handle string for our children.  */
       /* 2 hex digits per byte + 2 characters for "0x" + null.  */
+#ifdef WINDOWS32
+      static const char fmt[] = "0x%Ix";
+#else
+      static const char fmt[] = "%d";
+#endif
       sync_mutex = xmalloc ((2 * sizeof (sync_handle_t)) + 2 + 1);
-      sprintf (sync_mutex, "0x%Ix", handle);
+      sprintf (sync_mutex, fmt, handle);
       define_makeflags (1, 0);
     }
 }
 
 #endif  /* NO_OUTPUT_SYNC */
 
+#ifdef WINDOWS32
+
 /*
  * HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture
  * exception and print it to stderr instead.
diff --git a/src/output.c b/src/output.c
index e222e0a..3b22bbb 100644
--- a/src/output.c
+++ b/src/output.c
@@ -170,6 +170,42 @@ set_append_mode (int fd)
 /* Semaphore for use in -j mode with output_sync. */
 static sync_handle_t sync_handle = -1;
 
+
+/* Record in a static variable the mutex handle we were requested to
+   use.  That nameless mutex was created by the top-level Make, and
+   its handle was passed to us via inheritance.  The value of that
+   handle is passed via the command-line arguments, so that we know
+   which handle to use.  */
+void
+record_sync_mutex (const char *str)
+{
+  char *endp;
+  sync_handle_t hmutex = strtol (str, &endp, 16);
+
+  if (*endp == '\0')
+    sync_handle = hmutex;
+  else
+    {
+      sync_handle = -1;
+      errno = EINVAL;
+    }
+}
+
+/* Create a new mutex or reuse one created by our parent.  */
+static sync_handle_t
+init_sync_handle (void)
+{
+  /* If we have a mutex handle passed from the parent Make, just use
+     that.  */
+  if (sync_handle < 0)
+#ifdef WINDOWS32
+    sync_handle = create_mutex ();
+#else
+    sync_handle = output_tmpfd ();
+#endif
+  return sync_handle;
+}
+
 #define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
 
 /* Set up the sync handle.  Disables output_sync on error.  */
@@ -180,37 +216,36 @@ sync_init (void)
 
 #ifdef WINDOWS32
   if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
-      || (sync_handle = create_mutex ()) == -1)
+      || init_sync_handle () == -1)
     {
       perror_with_name ("output-sync suppressed: ", "stderr");
       output_sync = 0;
+      return 0;
     }
-  else
-    {
-      combined_output = same_stream (stdout, stderr);
-      prepare_mutex_handle_string (sync_handle);
-    }
+  combined_output = same_stream (stdout, stderr);
 
 #else
   if (STREAM_OK (stdout))
     {
       struct stat stbuf_o, stbuf_e;
 
-      sync_handle = fileno (stdout);
+      init_sync_handle ();
       combined_output = (fstat (fileno (stdout), &stbuf_o) == 0
                          && fstat (fileno (stderr), &stbuf_e) == 0
                          && stbuf_o.st_dev == stbuf_e.st_dev
                          && stbuf_o.st_ino == stbuf_e.st_ino);
     }
   else if (STREAM_OK (stderr))
-    sync_handle = fileno (stderr);
+    init_sync_handle ();
   else
     {
       perror_with_name ("output-sync suppressed: ", "stderr");
       output_sync = 0;
+      return 0;
     }
 #endif
 
+  prepare_mutex_handle_string (sync_handle);
   return combined_output;
 }
 
@@ -266,6 +301,7 @@ acquire_semaphore (void)
   fl.l_len = 1;
   if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
     return &fl;
+
   perror ("fcntl()");
   return NULL;
 }
@@ -369,6 +405,9 @@ output_dump (struct output *out)
          unsynchronized; still better than silently discarding it.
          We want to keep this lock for as little time as possible.  */
       void *sem = acquire_semaphore ();
+      if (sem == 0)
+        O (error, NILF, _(
+              "warning: Cannot acquire output lock, disabling output sync."));
 
       /* Log the working directory for this dump.  */
       if (print_directory && output_sync != OUTPUT_SYNC_RECURSE)
diff --git a/src/output.h b/src/output.h
index ece1c70..828a42a 100644
--- a/src/output.h
+++ b/src/output.h
@@ -102,14 +102,13 @@ int fcntl (intptr_t fd, int cmd, ...);
 intptr_t create_mutex (void);
 int same_stream (FILE *f1, FILE *f2);
 
-#  define RECORD_SYNC_MUTEX(m) record_sync_mutex(m)
-void record_sync_mutex (const char *str);
-void prepare_mutex_handle_string (intptr_t hdl);
 # else  /* !WINDOWS32 */
 
 typedef int sync_handle_t;      /* file descriptor */
 
-#  define RECORD_SYNC_MUTEX(m) (void)(m)
 
 # endif
+#  define RECORD_SYNC_MUTEX(m) record_sync_mutex(m)
+void record_sync_mutex (const char *str);
+void prepare_mutex_handle_string (sync_handle_t hdl);
 #endif  /* !NO_OUTPUT_SYNC */
diff --git a/src/w32/compat/posixfcn.c b/src/w32/compat/posixfcn.c
index 00d87e0..0207475 100644
--- a/src/w32/compat/posixfcn.c
+++ b/src/w32/compat/posixfcn.c
@@ -145,40 +145,13 @@ fcntl (intptr_t fd, int cmd, ...)
 }
 #endif /* GNULIB_defined_fcntl */
 
-static intptr_t mutex_handle = -1;
-
-/* Record in a static variable the mutex handle we were requested to
-   use.  That nameless mutex was created by the top-level Make, and
-   its handle was passed to us via inheritance.  The value of that
-   handle is passed via the command-line arguments, so that we know
-   which handle to use.  */
-void
-record_sync_mutex (const char *str)
-{
-  char *endp;
-  intptr_t hmutex = strtol (str, &endp, 16);
-
-  if (*endp == '\0')
-    mutex_handle = hmutex;
-  else
-    {
-      mutex_handle = -1;
-      errno = EINVAL;
-    }
-}
-
-/* Create a new mutex or reuse one created by our parent.  */
+/* Create a new mutex.  */
 intptr_t
 create_mutex (void)
 {
   SECURITY_ATTRIBUTES secattr;
   intptr_t hmutex = -1;
 
-  /* If we have a mutex handle passed from the parent Make, just use
-     that.  */
-  if (mutex_handle > 0)
-    return mutex_handle;
-
   /* We are the top-level Make, and we want the handle to be inherited
      by our child processes.  */
   secattr.nLength = sizeof (secattr);
@@ -195,7 +168,6 @@ create_mutex (void)
       hmutex = -1;
     }
 
-  mutex_handle = hmutex;
   return hmutex;
 }
 
