<br><br><div class="gmail_quote">On Wed, Feb 1, 2012 at 1:39 PM, Miguel Mudge <span dir="ltr"><<a href="mailto:michael.mudge@welchallyn.com">michael.mudge@welchallyn.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote"><div class="im">On Wed, Feb 1, 2012 at 9:48 AM, Rodrigo Kumpera <span dir="ltr"><<a href="mailto:kumpera@gmail.com" target="_blank">kumpera@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div class="gmail_quote"><div>On Wed, Feb 1, 2012 at 12:22 PM, Miguel Mudge <span dir="ltr"><<a href="mailto:michael.mudge@welchallyn.com" target="_blank">michael.mudge@welchallyn.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Yes, it's got machine exceptions.  With the help of the MMU, we are able to detect when the stack is down to the last 64K, so there is no need for an alternate stack.  We can call a function from there, somewhat akin to signals.</blockquote>



<div><br></div></div><div>On which stack and thread is that function called? You obviously can't call it on the overflown one.</div></div></blockquote><div><br></div></div><div><div>The RTOS is ThreadX for ARM - it is fairly useless.  Mono is supported mostly by a homebrew POSIX implementation wrapped around it [cringe].</div>


<br></div><div>We wrote our own MMU driver.  When an overflow occurs, we increase the size of the stack on the fly and call the overflow-handling function on the same thread and stack where the overflow occurred.  When that function returns, execution resumes on the instruction that caused the overflow, but this time with the larger stack.</div>


<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><div class="im"><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div>The requirements are that:</div><div>- The native code is allowed to continue execution.</div><div>- The managed code throws a StackOverflowException that executes finally blocks.</div><div>- The root AppDomain continues running.<br>





<div><br></div></div></blockquote></div></div><div class="im"><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>The out-of-memory exception is almost the exact same story... When memory gets low, I want to be able to do something that allows native code to continue, but OutOfMemoryException is thrown when execution returns to managed code.  I assume there is no mechanism in there for this?</div>



</div></blockquote><div><br></div></div><div>OOM is quite a different beast, it's handled synchronously since we know exactly when we're out of managed memory. Mono doesn't handle native allocation failures</div>


<div>
well and this is something I would love to see patches for. Managed allocation failures are well handled with sgen.</div></div></div>
</blockquote></div><br><div>Since Mono doesn't handle running out of system memory very well, I'd rather actually handle it in exactly the same way as StackOverflowException - free up some "guard memory" and throw the OutOfMemoryException when execution returns to native code.</div>


<div><br></div><div>In the context of our own requirements, I still see ThreadAbortException, StackOverflowException and OutOfMemoryException as ideally following the same code path.  In all 3 cases, a specific thread isn't prepared to handle the exception on the the exact instruction where it happens, so the exception gets thrown at the native->managed transition.</div>


<div><br></div><div>Perhaps I'm oversimplifying this - maybe the thread abort code is too specific to thread abort, and I certainly don't want to butcher it.  To me, so far, this looks like an opportunity to generalize code that was originally intended to be an exception [so to speak] to the way ThreadAbortException is thrown, compared to other exceptions.</div>


<div><br></div><div>We're also not super-familiar with all of Mono's existing facilities for this stuff - if there is a straightforward function we should call and/or adapt to our environment, that'd be quite helpful too.</div>


<div></div></blockquote></div><br><div><br></div><div>Now I see how and what you're trying to accomplish. Let's think in steps.</div><div><br></div><div>About OOM. The managed case is already handled for you, the unmanaged one will require some environment help. But your plan of releasing some guard memory and</div>
<div>then raising an OOM exception is sound.</div><div><br></div><div>To apply it to stack overflow is a bit trickier since you need  to handle the case where managed code is executing as well.</div><div><br></div><div>To handle native OOM, I guess patching the thread interruption code is the easier way to go. Change mono_thread_interruption_checkpoint_request to check for your OOM condition and you're set.</div>
<div><br></div><div>To handle stack overflow it will require a bit more work. You could patch mono_thread_interruption_checkpoint_request to check for it as well.</div><div>But would still need to patch the stack with a trampoline to raise the overflow exception in case it happens strictly on managed code.</div>
<div><br></div><div>And then you have a trickier issue, which is to reconquer soft guard pages from stack and memory allocator. This is specially important in case of stack overflow.</div><div><br></div><div><br></div>