<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On 15 May 2013, at 14:54, Siri Hansen wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">Then again... it is up to the child's start function to create the link, and from the supervisor's point of view, the only place to add the monitor would be when the start function returns - which would be just another place to get a race :(</div>
<div class="gmail_extra"><br></div></blockquote><div><br></div><div>Well quite. *sigh*</div><div><br></div><div>Perhaps what we do in cloud haskell might be instructive after all, though the approach runs counter to the APIs which its OTP forebears use. Our supervisor performs the actual `spawn' itself, so the child spec provides as its startup term (which is roughly equivalent to an MFArgs tuple), not a function which spawns the new process, but rather the code for its process' main loop. The disadvantage here is that the API is more constrained (in terms of what the main loop looks like), but the advantage is the supervisor can insert arbitrary code into the start phase of the child's server loop. Thus our supervisor performs the link (from child to parent) and forces the child process to wait until the monitor is set up correctly, before actually entering its loop. This ensures we don't end up with a race with regards startup, linking and monitor establishment. There relevant bit of the code looks roughly like this:</div><div><br></div><div><div>wrapClosure proc spec' =</div><div> let chId = childKey spec' in do</div><div> supervisor <- getSelfPid</div><div> pid <- spawnLocal $ do</div><div> link supervisor -- die if our parent dies</div><div> () <- expect -- wait for a start signal</div><div> proc >>= checkExitType chId -- evaluate the child's loop</div><div> void $ monitor pid -- synchronous call to establish a monitor</div><div> send pid () -- tell the child to go into its main loop</div><div> return $ Right $ ChildRunning pid</div></div><div><br></div><div>Of course, because of this design, our gen_server API looks completely different! The start function, for example, doesn't spawn a process, but rather evaluates the `init' callback and enters the gen server's main loop (or crashes) immediately with the return value, leaving the `spawn' part to its clients. The supervisor is, of course, one of these clients: In fact our supervisor, like it's OTP inspiration, is itself a gen_server (we call them managed processes), and thus its start function never returns either:</div><div><br></div><div>-- | Starts a supervisor. </div><div>...</div><div>start :: RestartStrategy -> [ChildSpec] -> ManagedProcessLoop SupervisorState</div><div>start strategy' specs' = ManagedProcess.start (strategy', specs') supInit serverDefinition</div><div><br></div><div>Now obviously, given that Erlang has been used in the real world for decades, we can't go changing gen server's start_link or the supervisor child spec APIs. But is there a way to achieve something similar without carving things up too much? I'm struggling to think of one, but it would good if we could avoid the race altogether.</div><div><br></div><div>Cheers,</div><div>Tim</div><br><blockquote type="cite"><div class="gmail_extra"><br><div class="gmail_quote">2013/5/15 Tim Watson <span dir="ltr"><<a href="mailto:watson.timothy@gmail.com" target="_blank">watson.timothy@gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div class="im"><div>On 15 May 2013, at 11:17, Robert Virding wrote:</div></div><div><div class="im"><br><blockquote type="cite"><span style="border-collapse:separate;font-family:Helvetica;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><div>
<div style="font-size:12pt;font-family:'times new roman','new york',times,serif">Do you mean only using monitors in the supervisor, and no links? If so that would not work as you would then not get an exit signal automatically sent to the child when the supervisor dies.</div>
</div></span></blockquote><div><div><blockquote type="cite"><div><div style="font-size:12pt;font-family:'times new roman','new york',times,serif">Which you do want. Or have I misunderstood you?<br><br></div>
</div></blockquote><br></div></div></div><div>Oh gosh, how embarrasing. I was thinking in terms of <span style="font-family:NimbusRomNo9L;font-size:12px;font-weight:500">Uni-directional Links (viz A Unified Semantics for Future Erlang, Svensson et al), and linking child to parent (so as to propagate supervisor exits) but not the other way around. Of course we can't do that - just ignore this suggestion. [note: </span>I've been implementing the supervisor API for cloud haskell in my spare time and got confused between those semantics (viz <a href="http://haskell-distributed.github.io/static/semantics.pdf" target="_blank">http://haskell-distributed.github.io/static/semantics.pdf</a>) and what I do for a day job in the *real world*].</div>
<div><br></div><div>But switching all the supervisor's signal handling to rely on monitor notifications rather than trapped exits (which might be ignored) sounds good to me. The use of linking would be there to guarantee supervisor death is propagated correctly, but we could switch away from handling child 'EXIT' signals to handling 'DOWN' notifications instead. This would IMO be a bit cleaner.</div>
<div><br></div><div>Cheers,</div><div>Tim</div></div></div></blockquote></div><br></div>
</blockquote></div><br></body></html>