Web lists-archives.com

[PATCH RFC] fork: reduce chances for "address space is already occupied" errors

Hi Corinna,

as I do still encounter fork errors (address space needed by <dll> is already occupied)
with dynamically loaded dlls (but unrelated to replaced dlls), one of them repeating
even upon multiple retries, I'm coming up with attached patch.

What do you think about it?

>From dfc28bcbb7ed55fe33ddb8d15e761b4d5b4815f8 Mon Sep 17 00:00:00 2001
From: Michael Haubenwallner <michael.haubenwallner@xxxxxxxxxxxxxxxx>
Date: Tue, 26 Mar 2019 17:38:36 +0100
Subject: [PATCH] Cygwin: fork: reserve dynloaded dll areas earlier

In dll_crt0_0, both threadinterface->Init and sigproc_init allocate
windows object handles using unpredictable memory regions, which may
collide with dynamically loaded dlls when they were relocated.
 winsup/cygwin/dcrt0.cc | 6 ++++++
 winsup/cygwin/fork.cc  | 6 ------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 11edcdf0d..fb726a739 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -632,6 +632,12 @@ child_info_fork::handle_fork ()
   if (fixup_mmaps_after_fork (parent))
     api_fatal ("recreate_mmaps_after_fork_failed");
+  /* We need to occupy the address space for dynamically loaded dlls
+     before we allocate any dynamic object, or we may end up with
+     error "address space needed by <dll> is already occupied"
+     for no good reason (seen with some relocated dll). */
+  dlls.reserve_space ();
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 74ee9acf4..7e1c08990 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -136,12 +136,6 @@ frok::child (volatile char * volatile here)
   HANDLE& hParent = ch.parent;
-  /* NOTE: Logically this belongs in dll_list::load_after_fork, but by
-     doing it here, before the first sync_with_parent, we can exploit
-     the existing retry mechanism in hopes of getting a more favorable
-     address space layout next time. */
-  dlls.reserve_space ();
   sync_with_parent ("after longjmp", true);
   debug_printf ("child is running.  pid %d, ppid %d, stack here %p",
 		myself->pid, myself->ppid, __builtin_frame_address (0));

Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple