The cygheap saga
Pierre A. Humblet
Pierre.Humblet@ieee.org
Sat Apr 3 01:50:00 GMT 2004
At 10:37 PM 4/1/2004 -0500, Christopher Faylor wrote:
>On Thu, Apr 01, 2004 at 09:36:14PM -0500, Pierre A. Humblet wrote:
>>At 06:11 PM 4/1/2004 +0200, Corinna Vinschen wrote:
>>>
>>>AFAICS, we have currently three pressing problems:
>>>
>>>- People complaining about cygheap problems (Win32 error 487) but
>>> nobody willing to debug it.
>>
>>I will describe how it works (details in how-cygheap-works),
>>and then how we might change that to improve the chance of
>>success.
>>
>>1) When starting, Cygwin tries to reserve an amount of memory Pr
>> as large as possible with CYGHEAPSIZE >= Pr >= CYGHEAPSIZE_MIN
>> The initial committed memory size Pc is 0.
>>2) As Cygwin operates and calls csbrk , Pc grows. Pc can grow
>> past Pr, although that is unlikely, and in fact impossible if
>> Pr < CYGHEAPSIZE. csbrk calls will not fail as long as Pc <= Pr.
>>3) When starting a child, the parent creates a file mapping of size
>> Max(Pc, Pr), copies Pc bytes to it and passes the handle to the child.
>>4) The child tries to map the region to the same address as the parent's
>> heap. If that works, the child is done.
>>5) Else the child tries to reserve Max(Pc, Pr) at the same address
>> as the parent's heap.
>>6) The child then commits and copies Pc bytes from the file mapping to
>> that region.
>>The failure occurs in step 5.
>>
>>What I don't see if why we need to reserve Max(Pc, Pr) and not simply
>>a quantity Cr with Pr >= Cr >= Pc or Pr >= Cr >= max(Pc, CYGHEAPSIZE_MIN).
>>We could even try to make Cr as large as CYGHEAPSIZE, but if the parent
>>did not succeed I would think the child won't either.
>>As an aside, I am wondering if the current step 5 can ever work (on NT)
>>if step 4 has failed. Why would 4 fail if space is available?
>
>Let me make it really simple.
>
>Parent is reserving X amount of space.
>
>Child can't reserve that much space because something (probably a DLL)
>is blocking the reservation of the full amount of space.
>
>Before we change the design, we need to find out what is blocking the
>reservation of the memory rather than just making the child allocate less
>space than the parent.
Why not do both, given that this problem seems to pop up regularly?
At any rate I had written a patch and I tested on NT today (on a machine
without problem). The curious can try it. It's a fairly simple patch.
Pierre
-------------- next part --------------
Index: cygheap.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/cygheap.cc,v
retrieving revision 1.101
diff -u -p -r1.101 cygheap.cc
--- cygheap.cc 26 Mar 2004 22:48:47 -0000 1.101
+++ cygheap.cc 2 Apr 2004 20:02:08 -0000
@@ -144,17 +144,35 @@ cygheap_fixup_in_child (bool execed)
{
cygheap = child_proc_info->cygheap;
cygheap_max = child_proc_info->cygheap_max;
+ alloc_sz = child_proc_info->cygheap_alloc_sz;
void *addr = !wincap.map_view_of_file_ex_sucks () ? cygheap : NULL;
void *newaddr;
newaddr = MapViewOfFileEx (child_proc_info->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, addr);
- alloc_sz = child_proc_info->cygheap_alloc_sz;
if (newaddr != cygheap)
{
- if (!newaddr)
- newaddr = MapViewOfFileEx (child_proc_info->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, NULL);
DWORD n = (DWORD) cygheap_max - (DWORD) cygheap;
- /* Reserve cygwin heap in same spot as parent */
+ if (addr)
+ {
+ alloc_sz = n + (128 * 1024); /* Minimum */
+
+ if (!newaddr)
+ newaddr = MapViewOfFileEx (child_proc_info->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, NULL);
+
+ MEMORY_BASIC_INFORMATION m;
+
+ if (!VirtualQuery ((LPCVOID) cygheap, &m, sizeof m))
+ debug_printf ("couldn't get memory info, %E");
+
+ else if ((char *) m.BaseAddress + m.RegionSize >= (char *) cygheap + alloc_sz)
+ alloc_sz = (char *) m.BaseAddress - (char *) cygheap + m.RegionSize;
+
+ system_printf ("Desired: %d Reserved: %d Committed %d",
+ child_proc_info->cygheap_alloc_sz, alloc_sz, n);
+ }
+ if (!newaddr)
+ api_fatal ("MapViewOfFileEx failed");
+ /* Reserve cygwin heap in same spot as parent */
if (!VirtualAlloc (cygheap, alloc_sz, MEM_RESERVE, PAGE_NOACCESS))
{
MEMORY_BASIC_INFORMATION m;
@@ -167,15 +185,14 @@ cygheap_fixup_in_child (bool execed)
api_fatal ("m.AllocationBase %p, m.BaseAddress %p, m.RegionSize %p, m.State %p\n",
m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
}
-
- /* Allocate same amount of memory as parent */
+
+ /* Commit same amount of memory as parent */
if (!VirtualAlloc (cygheap, n, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
cygheap, n);
memcpy (cygheap, newaddr, n);
UnmapViewOfFile (newaddr);
}
-
ForceCloseHandle1 (child_proc_info->cygheap_h, passed_cygheap_h);
cygheap_init ();
More information about the Cygwin-developers
mailing list