<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
--></style>
</head>
<body class='hmmessage'>
 > What happens to the dead threads in the child when they get GC'd?   <BR>
 > Their finaliser will try to invoke CleanThread which might fail because <BR>
 > the threads mutex/cond are in a bad state in the child.  Is that possible? <BR>
 <BR>
 <BR>
This is what pthread_atfork is for.<BR>
I'm not sure you don't realize that, or are pointing out that I wasn't handling everything.<BR>
  You see the question mark in the ThreadPThread.AtForkPrepare in the diff I sent? That covers this..and I think indeed it needs work:<BR>
 <BR>
 <BR>
I think for this reason Thread.AtForkPrepare should walk all the threads and take their locks, and then child will release them all, and we can go ahead and cleanup them up right away as well (in the child), we might otherwise lose all references to them, since they were in thread locals.<BR>
 <BR>
 <BR>
I think AtForkPrepare needs to broadly speaking, acquire *all* locks.<BR>
Not just some.<BR>
The diffs I sent only take some.<BR>
I will include this change in next set of diffs -- the ones that will also change user threads to not inherit threads after RTProcess.Fork().<BR>
 <BR>
 <BR>
I suspect this is a difficult task in some code bases.<BR>
And I'm not sure I suggest clean this up throughout cm3.<BR>
However we can at least address RTCollector.m3 and ThreadPThread.m3 and get cvsup working.<BR>
And then we could be like Apple and the docs could just say "fork not followed by exec not guaranteed to work much".<BR>
?<BR>
 <BR>
 <BR>
Also makes me wonder..we should provide wrapped up fork+exec, eh, we already do. It is in libm3. It should probably be in m3core, but I don't think that difference matters too much.<BR>
 <BR>
 <BR>
 - Jay<BR><BR> <BR>
<HR id=stopSpelling>
From: hosking@cs.purdue.edu<BR>Date: Fri, 19 Mar 2010 14:49:14 -0400<BR>To: jay.krell@cornell.edu<BR>CC: m3devel@elegosoft.com<BR>Subject: Re: [M3devel] cvsup fix refinements<BR><BR><BASE>
<DIV>
<DIV>On 19 Mar 2010, at 14:15, Jay K wrote:</DIV><BR class=ecxApple-interchange-newline>
<BLOCKQUOTE><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; WORD-SPACING: 0px" class=ecxApple-style-span>
<DIV style="FONT-FAMILY: Verdana; FONT-SIZE: 10pt" class=ecxhmmessage>RTProcess is fine.<BR>Unix is a little wierd because I don't think it should do anything if using userthreads.<BR></DIV></SPAN></BLOCKQUOTE>
<DIV><BR></DIV>
<DIV>I think forking with user threads should have the same behaviour as with system threads: all threads except the forker will die.</DIV>
<DIV>Another thing.  What happens to the dead threads in the child when they get GC'd?  Their finaliser will try to invoke CleanThread which might fail because the threads mutex/cond are in a bad state in the child.  Is that possible?</DIV><BR>
<BLOCKQUOTE><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; WORD-SPACING: 0px" class=ecxApple-style-span>
<DIV style="FONT-FAMILY: Verdana; FONT-SIZE: 10pt" class=ecxhmmessage>Unix implies a fairly thin wrapper?<BR><BR> - Jay<BR><BR><BR>
<HR id=ecxstopSpelling>
Subject: Re: [M3devel] cvsup fix refinements<BR>From:<SPAN class=ecxApple-converted-space> </SPAN><A href="mailto:hosking@cs.purdue.edu">hosking@cs.purdue.edu</A><BR>Date: Fri, 19 Mar 2010 14:13:32 -0400<BR>CC:<SPAN class=ecxApple-converted-space> </SPAN><A href="mailto:m3devel@elegosoft.com">m3devel@elegosoft.com</A><BR>To:<SPAN class=ecxApple-converted-space> </SPAN><A href="mailto:jay.krell@cornell.edu">jay.krell@cornell.edu</A><BR><BR>Why not put it into RTProcess?
<DIV>Or into Unix?<BR>
<DIV>
<DIV>I want to avoid confusion between Thread.Fork (fork a thread) and process fork.</DIV>
<DIV><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span>
<DIV style="WORD-WRAP: break-word"><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: 12px Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px" class=ecxecxApple-style-span>
<DIV><SPAN style="FONT-SIZE: medium" class=ecxecxApple-style-span><FONT class=ecxecxApple-style-span color=#0000ff face="'Gill Sans'"><BR></FONT></SPAN></DIV></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></DIV></SPAN></SPAN></DIV>
<DIV>
<DIV>On 19 Mar 2010, at 14:08, Jay K wrote:</DIV><BR class=ecxecxApple-interchange-newline>
<BLOCKQUOTE><SPAN style="TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Helvetica; WHITE-SPACE: normal; LETTER-SPACING: normal; WORD-SPACING: 0px" class=ecxecxApple-style-span>
<DIV style="FONT-FAMILY: Verdana; FONT-SIZE: 10pt" class=ecxecxhmmessage> > could go in any of ThreadF, RTOS, RTProcess?<BR><BR><BR>Or RTThread. Or almost anywhere.<BR><BR><BR>Some typos in the diffs:<BR> in a comment, ThreadF__ should be RTOS__<BR> function PThreadForkHandler named inconsistently,<BR>  should be PThreadAtForkHandler<BR><BR><BR>Again, "PThread" appears in these names to indicate<BR>their meaning is not portable. Their existance is, but not their meaning.<BR>We have no way of saying "only call this function for pthreads",<BR>instead as I understand, we provide a portable interface with<BR>drastically varying semantics, such as "do something" vs. "do nothing".<BR><BR><BR>Given that Init in ThreadPThread.m3 is private, we could probably<BR>take the stackbase parameter from the caller instead.<BR><BR><BR>The call to AtFork should probably follow InitWithStackbase,<BR>in case it fails under low memory, the Die/assert more likely to "work".<BR><BR><BR>I'm not completely happy making RTOS public.<BR> So maybe ThreadF?<BR> I had gone to RTOS because SetNextForkWillExec required LockHeap/UnlockHeap.<BR> But for now they don't exist.<BR><BR><BR>Maybe a new interface? ThreadPThread.i3, but is still<BR>present on all platforms, so mostly portable can call it.<BR><BR><BR>ThreadPThread.AtFork?<BR>PThread.AtFork? That seems right.<BR><BR><BR> - Jay<BR><BR><BR>
<HR id=ecxecxstopSpelling>
From:<SPAN class=ecxecxApple-converted-space> </SPAN><A href="mailto:jay.krell@cornell.edu">jay.krell@cornell.edu</A><BR>To:<SPAN class=ecxecxApple-converted-space> </SPAN><A href="mailto:m3devel@elegosoft.com">m3devel@elegosoft.com</A><BR>Date: Fri, 19 Mar 2010 17:21:13 +0000<BR>Subject: Re: [M3devel] cvsup fix refinements<BR><BR>diffs attached<BR><BR><BR>For now I've removed the Get/SetNextForkWillExec.<BR> I also think truly get/set is right, not inc/dec.<BR> It was confusing enough to interpret and initialize<BR> the value. And it is also not clear what the default<BR> should be. The usual behavor is exec does follow fork.<BR> The safer default if the handlers work ok is to assume<BR> exec will not follow. It is a perf hint or a don't change<BR> how things were hint? Hint to speed up fork+exec or hint<BR> to avoid running the new code that might not work?<BR><BR><BR>(For now I've removed the Get/SetNextForkWillExec.)<BR>  They'd have to be implemented three times, and<BR>  I had trouble defining them.<BR>  Obviously Win32/userthreads just return a<BR>  hardcoded true, but it is hard to explain<BR>  from the caller of Get's point of view.<BR><BR>Maybe:<BR>  SetNextForkWillExec<BR>  GetNextForkWillExec<BR> <SPAN class=ecxecxApple-converted-space> </SPAN><BR>and then:<BR>  PThreadAtForkNeeded() = GetNextForkWillExec = FALSE ?<BR><BR>That is,<BR> someone is who is calling fork and possibly exec,<BR> can immediately tell what these functions mean.<BR><BR>  <SPAN class=ecxecxApple-converted-space> </SPAN><BR>But the implementer of an atfork handler has to<BR>  do quite a semantic translation I think.<BR>  I wrote it backwards the first time. That either<BR>  implies it is confusing, or I wasn't thinking.<BR> <SPAN class=ecxecxApple-converted-space> </SPAN><BR><BR>If it really is a problem to run this stuff when exec<BR>will follow, we should know quickly, as building cm3<BR>is an aggressive user of this code.<BR><BR><BR>This version has worked repeatedly on Darwin.<BR>I didn't test user threads but it is structured such<BR>as to make that obviously work.<BR>  The cvsup changes are in pthreaad_atfork handlers,<BR>  so no change for userthreads.<BR><BR><BR>I didn't test on others but confidence is quite high now.<BR><BR>description of changes at least where they are hard to read:<BR><BR>m3core:<BR>  Init split into Init and InitWithStackBase,<BR>    We have to provide the old stack base in the child fork handler<BR>    instead of estimating from the address of a local. I don't<BR>    know what stack is used, maybe the caller of fork?<BR>    i.e. we might have eaten a fair amount of stack and<BR>    there could be arbitrary references above the current stack.<BR><BR><BR>WeakRefFromRef split into WeakRefFromRef and StartWeakCleaner<BR><BR>There is a resulting double lock in WeakRefFromRef, every time.<BR>Could instead copy/paste more code around, i.e.:<BR>      EVAL Thread.Fork(NEW(Thread.Closure, apply := WeakCleaner));<BR><BR><BR> - Jay<BR><BR><BR><BR><BR><BR><BR>
<HR id=ecxecxecxstopSpelling>
From:<SPAN class=ecxecxApple-converted-space> </SPAN><A href="mailto:jay.krell@cornell.edu">jay.krell@cornell.edu</A><BR>To:<SPAN class=ecxecxApple-converted-space> </SPAN><A href="mailto:m3devel@elegosoft.com">m3devel@elegosoft.com</A><BR>Date: Fri, 19 Mar 2010 16:01:03 +0000<BR>Subject: [M3devel] cvsup fix refinements<BR><BR>refinements:<BR><BR><BR>new public functions in m3core:<BR><BR><BR>TYPE PThreadForkHandler = PROCEDURE();<BR><BR><* EXTERNAL RTOS__PThreadAtFork *><BR>PROCEDURE PThreadAtFork(prep, parent, child: PThreadForkHandler): INTEGER;<BR><BR><BR>(That's not a change yet.)<BR><BR><BR>PROCEDURE SetNextForkWillExec(value: BOOLEAN);<BR><BR>PROCEDURE GetNextForkWillExec(): BOOLEAN;<BR><BR> These are only an optimization and should<BR> perhaps be removed? They should be used<BR> under LockHeap/UnlockHeap? which wasn't previously<BR> public. This way, existing fork/exec paths<BR> not affected, though maybe though might as well<BR> ought to be?<BR><BR><BR>could go in any of ThreadF, RTOS, RTProcess?<BR><BR><BR>Should be called under RTOS.LockHeap?<BR>  Therefore I put in RTOS.<BR>  Also helps that RTOS is exported from *Thread.m3.<BR>RTOS not previously public.<BR><BR><BR>Should Get/Set be Inc/Dec? (therefore just Inc with +1,-1?)<BR> I implemented them that way: true incs, false decs.<BR><BR><BR>Or don't bother with them at all?<BR><BR><BR>Furthermore, in RTCollector, instead of claiming the threads<BR>aren't started, if they were started, restart them.<BR>This makes more sense for the weak cleaner to me, and<BR>seems reasonable for the other two.<BR><BR><BR>Diffs not yet available.<BR><BR><BR> - Jay<BR></DIV></SPAN></BLOCKQUOTE></DIV><BR></DIV></DIV></DIV></SPAN><BR class=ecxApple-interchange-newline></BLOCKQUOTE></DIV><BR>                                         </body>
</html>