Subject: Re: CYGWin fork() + Parent->Child Stack replicate algorithm
From: Christopher Faylor <[email-masked]>
To: [email-masked]
Cc: "Faccini, Bruno" <[email-masked]>
Date: Wed, 19 Sep 2001 14:08:16 -0400

To answer these questions in the appropriate forum.

Did I mean "main thread" and "non-main thread" when I said "main thread"
and "non-main thread"?  Yes.  I have no idea what you could have thought
I would be referring to.

Did I ignore some cases in alloc_stack_hard_way?  I don't remember.

Did I leave the old relocated stack around?  Probably.

Can it be freed via VirtualFree?  Don't know.

cgf

On Wed, Sep 19, 2001 at 01:52:16PM -0400, Christopher Faylor wrote:
>Please check out the project web page for links to available information
>and ports:  http://cygwin.com/ .
>
>If you don't see what you need there, then the cygwin mailing list is
>the best place to make observations or get questions answered.
>Information on the mailing list is available at the project web page.
>
>For your convenience, I've reset the Reply-To: address to point to the
>cygwin mailing list.  I've also Cc'ed this reply there.
>
>On Wed, Sep 19, 2001 at 06:14:49PM +0100, Faccini, Bruno wrote:
>>
>>Hello,
>>
>>I just found an email answer from you about a problem/question around the
>>"CYGWin fork() + Parent->Child Stack replicate algorithm" that you told to
>>be the author/main-developer.
>>
>>As an exercise to understand Win32 internals+API, I am currently trying to
>>understand the internal mechanisms of the CYGWin "fork()" implementation on
>>top of Win32 and I am particulary interested in the way you
>>replicate+manipulate Child's Stack from the Parent's image (I am
>>using/working-on the most recent "cygwin-1.3.[1,2,3]-1" pkgs actually). 
>>Doing/looking-at this, I found that "alloc_stack_hard_way()" is
>>handling+doing some condition/stuff I do not fully understand for now. Can
>>you help/answer me ??
>>If yes, here are the points I need to be explained/highlighted :
>>	_ What do you mean by "alloc_stack_hard_way is executed when a fork
>>is performed from something other than the non-main thread" (your
>>comment/answer in the email thread where I found your references) ?? Do you
>>meant "main thread" vs "non-main thread" in fact ?? Then, do you refer to
>>the fact (and underlying Win32 Threads scheme) that "non-main threads" will
>>have new Stack segments/Regions allocated and thus different address ranges
>>than the "main" thread of both the Parent and the Child process ??
>>	_ looking more indeep in both "alloc_stack()/alloc_stack_hard_way()"
>>algorithm, I am a little-bit stuck with what you are checking+doing there
>>... I tend to understand that you try to check and fix the case where
>>"fork()" was called in/from a "Parent non-standard Stack
>>situation/address-range" (am I right there ??), but what do you really
>>address by the following "alloc_stack()/alloc_stack_hard_way()" code
>>sequences, prior to "longjmp()" the Child to its Parent replicated Stack :
>>----------------------------------------------------------------------------
>>-------
>>...
>>// __inline__ void
>>extern void
>>alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
>>{
>>  void *new_stack_pointer;
>>  MEMORY_BASIC_INFORMATION m;
>>  void *newbase;
>>  int newlen;
>>  LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
>>  bool noguard;
>>
>>  if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
>>    {
>>      newbase = curbot;
>>      newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
>>      noguard = 1;
>>    }
>>  else
>>    {
>>      newbase = ci->stacktop;
>>      newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
>>      noguard = 0;
>>    }
>>  if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
>>....
>>
>>static void
>>alloc_stack (child_info_fork *ci)
>>{
>>  /* FIXME: adding 16384 seems to avoid a stack copy problem during
>>     fork on Win95, but I don't know exactly why yet. DJ */
>>  volatile char b[ci->stacksize + 16384];
>>
>>  if (ci->type == PROC_FORK)
>>    ci->stacksize = 0;		// flag to fork not to do any funny business
>>  else
>>    {
>>      if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
>>	api_fatal ("fork: couldn't get stack info, %E");
>>
>>      if (sm.AllocationBase != ci->stacktop)
>>	alloc_stack_hard_way (ci, b + sizeof (b) - 1);
>>      else
>>
>>.....
>>
>>----------------------------------------------------------------------------
>>---------
>>
>>You seem to assume+ignore some cases/scenarios here, like (and if I refer to
>>"ci->[stack[top,size,bottom]]." stuff to describe the Parent's/fork()'ing
>>current Stack allocation and the
>>"sm.[AllocationBase,BaseAddress,RegionSize]" stuff to the Child's/fork()'ed
>>current Stack allocation) "sm.AllocationBase" < "ci->stacktop" <
>>"ci->stackbottom" < "curbot".
>>
>>Are these cases identified as not possible with Win32 Processes/Threads
>>Stack allocation scheme ?? What about the Linker's "/STACK" option usage and
>>behavior, or possible manual/explicit "VirtualAlloc()/VirtualFree()" earlier
>>actions in the Parent/fork()'ing process/thread and for its Stack
>>address-range ??
>>
>>And what about free'ing/VirtualFree() of the original but now possible
>>unused/left pieces (like in the case of fully separate Parent and
>>original/default Child Stacks adress ranges) ??
>>
>>Thank's in advance for your help/answer but also for your
>>participation/great job to have this wonderfull CYGWin product/suite
>>work/run so fine and for free + open-source.

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/