Hi all,

I have recently been plagued by the 'Cannot fork: Resource temporarily unavailable' problem.

Searching the web reveals the there are about half as many solutions as there are people complaining about it, none of which work for me (or the other half of the complaining people, apparently).

If I'm wrong about this then stop me now, and tell me how I should have fixed it. :)

Anyway, here's *my* solution, and hopefully this one can be made to work for other people also.

The attached patch adds a 'retry' to the fork system call. Basically it waits 10 seconds to allow the 'resource temporarily unavailable' to become (temporarily) available once more, and tries again, up to a maximum of three attempts.

It also saves a log file (under /tmp) so that I can see whether it is doing anything or not - the problem is impossible to reproduce at will. This is merely a debugging aid and should be removed from the final patch. I did a complete build of our product and the log file indicates the problem was averted twice. On both occasions a single retry was sufficient.

I do not claim that this patch is in any way ready to commit. It is merely a proof of concept.

I do not know what the requirements are for submission of patches to this project. If I require any sort of copyright assignment then please feel free to use my idea, but I shall not be able to help with the final implementation.

I hope we can find some acceptable way of solving this nasty problem.

Andrew Stubbs
--- cygwin-1.5.24-2.orig/winsup/cygwin/fork.cc  2007-01-23 17:16:59.001000000 
+0000
+++ cygwin-1.5.24-2/winsup/cygwin/fork.cc       2007-11-14 13:01:48.981500000 
+0000
@@ -37,6 +37,8 @@ details. */
 /* FIXME: Once things stabilize, bump up to a few minutes.  */
 #define FORK_WAIT_TIMEOUT (300 * 1000)     /* 300 seconds */
 
+extern "C" int wrappedfork();
+
 class frok
 {
   dll *first_dll;
@@ -47,7 +49,7 @@ class frok
   int this_errno;
   int __stdcall parent (void *esp);
   int __stdcall child (void *esp);
-  friend int fork ();
+  friend int wrappedfork ();
 };
 
 static void
@@ -512,7 +514,7 @@ cleanup:
 }
 
 extern "C" int
-fork ()
+wrappedfork ()
 {
   frok grouped;
   MALLOC_CHECK;
@@ -580,6 +582,37 @@ fork ()
   syscall_printf ("%d = fork()", res);
   return res;
 }
+
+extern "C" int
+fork ()
+{
+  int i;
+  int result;
+
+  for (i=0; i<3; i++)
+    {
+      if (i > 0)
+        {
+          Sleep (10000);
+
+          debug_printf ("wrappedfork: retry %d\n", i);
+
+         FILE *fd = fopen ("/tmp/fork.log", "a");
+         fprintf (fd, "Fork failed: errno = %d, retry = %d\n", errno, i);
+          fclose (fd);
+        }
+
+      result = wrappedfork ();
+
+      if (result != -1)
+       break;
+
+      debug_printf ("wrappedfork() failed\n");
+    }
+
+  return result;
+}
+
 #ifdef DEBUGGING
 void
 fork_init ()

Reply via email to