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 ()