On Tue, Sep 14, 2010 at 5:45 AM, Nicolas Bertolotti <span dir="ltr"><<a href="mailto:Nicolas.Bertolotti@mathworks.fr">Nicolas.Bertolotti@mathworks.fr</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div link="blue" vlink="purple" lang="FR"><div>
<span lang="EN-US">It appears that, when stderr is not
accessible, the toplevel handler which attempts to write its own message
generates an exception that causes the infinite loop.</span>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span lang="EN-US">I tried to fix the issue in
basis-library/mlton/exn.sml but I could not manage to eliminate the issue:</span></p>
<p><span lang="EN-US"><span>-<span style="font: 7pt "Times New Roman";">
</span></span></span><span lang="EN-US">The exceptions that may occur
in the call to “message” seem to be properly handled</span></p>
<p><span lang="EN-US"><span>-<span style="font: 7pt "Times New Roman";">
</span></span></span><span lang="EN-US">If I add a global ref that I
set to true the first time I enter the function and that prevents it from
running again, it has no effect.</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span lang="EN-US">Any thought?</span></p></div></div></blockquote><div><br>Turns out the issue is quite simple. In <src>/basis-library/mlton/exn.sml, we have the default top-level handler:<br>
<br> val message = PrimitiveFFI.Stdio.print<br> val defaultHandler = fn exn =><br> (message (concat ["unhandled exception: ", exnMessage exn, "\n"])<br> ; (case history exn of<br>
[] => ()<br> | l =><br> (message "with history:\n"<br> ; List.app (fn s => message (concat ["\t", s, "\n"])) l))<br>
; Exit.exit Exit.Status.failure)<br> <br>The PrimitiveFFI.Stdio.print function comes from <src>/runtime/basis/Stdio.c:<br><br>void Stdio_printStderr (String8_t s) {<br> uintmax_t size = GC_getArrayLength ((pointer)s);<br>
if (0 == size)<br> return;<br> while (1 != fwrite ((const void*)s, (size_t)size, 1, stderr))<br> /* nothing */;<br>}<br><br>void Stdio_print (String8_t s) {<br> Stdio_printStderr (s);<br>}<br><br>So, the infinite loop is just the while loop that tries to print out the message, but keeps getting back -1 (with errno == EPIPE). It seems reasonable to repeat the write if 0 is returned (a "short" write), but we should only repeat the write if errno == EINTR. And, even then, the only time we use the Stdio_print function is at times of last resort, so it isn't clear that other errors are likely to be recoverable.<br>
<br></div></div>