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

Corinna Vinschen corinna-cygwin@cygwin.com
Thu Mar 28 09:16:00 GMT 2019

On Mar 28 09:34, Michael Haubenwallner wrote:
> Hi Corinna,
> On 3/27/19 10:16 AM, Corinna Vinschen wrote:
> > On Mar 27 09:26, Michael Haubenwallner wrote:
> >> On 3/26/19 7:28 PM, Corinna Vinschen wrote:
> > Wait, let me understand what's going on.  IIUC you're building DLLs
> > which are then used during the build job itself, right?
> Exactly.
> FWIW, the CI builds also set up a Cygwin instance from scratch,
> as I'm also after testing Cygwin (v3) itself to some degree:
> https://dev.azure.com/gentoo-prefix/ci-builds/_build
> However, I've not found a commandline option for setup.exe to install
> "test" versions...
> > As you know, 64 bit has a defined memory layout.  Binutils ld is
> > supposed to base the DLLs to a pseudo-random address in the area between
> > 0x4:00000000 and 0x6:00000000.  This area is occupied by un-rebased DLLs
> > only.  8 Gigs is a *lot* of space for DLLs.
> > 
> > That also means that the DLLs should not at all collide with windows
> > objects (typically reserved in the lesser 2 Gigs area), unless they
> > collide with themselves.  At least that's the idea.
> > 
> > Can you check what addresses the freshly built DLLs are based on by LD?
> > Is there a chance that the algorithm used in LD is too dumb?
> I've also added system_printf to dll_list::reserve_space() when a dynloaded
> dll was relocated, and each new address was below 0x0:01000000. The attached
> output also contains the preferred address, above 0x4:00000000 each.

Do they actually collide with each other?  Did you check the addresses?

> > Or, hmm.  Is there a chance that newer Windows loads dynamically loaded
> > DLLs whereever it likes, ignoring the base address, ASLR-like, even
> > if the DLL is marked as non-ASLR-aware?  But then again, we should have
> > a lot more complaints on the list...
> I've done this test on Windows Server 2012R2, but the problem exists on
> 2016 and 2019 as well (I'm not testing with other Windows versions).

I wrote an STC:

#include <stdio.h>
#include <dlfcn.h>

int main ()
  void *a, *b, *c;

  printf ("vor 1. dlopen\n");
  getchar ();
  a = dlopen ("/usr/bin/cyggomp-1.dll", RTLD_NOW);
  printf ("loaded cyggomp-1.dll\n");
  getchar ();
  b = dlopen ("/usr/bin/cyggs-9.dll", RTLD_NOW);
  printf ("loaded cyggs-9.dll\n");
  getchar ();
  c = dlopen ("/usr/bin/cyggtk-3-0.dll", RTLD_NOW);
  printf ("loaded cyggtk-3-0.dll\n");
  getchar ();
  return 0;

Checking the DLL addresses after each step in the /proc maps file.

The weird thing here is, *all* DLLs, not only the directly loaded,
but also all indirectly loaded dependencies are loaded to their
expected base address between 0x2:00000000 and 0x4:00000000.

There must be collisions in your case.  Can you please check if
Achim's solution works for you?

In the meantime I pushed your patch to the master branch (but not
yet to the 3.0 branch).


Corinna Vinschen
Cygwin Maintainer
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin-patches/attachments/20190328/89986dd1/attachment.sig>

More information about the Cygwin-patches mailing list