[Mono-dev] Handling StackOverflow, OutOfMemory, ThreadAbortException

Miguel Mudge michael.mudge at welchallyn.com
Tue Feb 7 23:31:58 UTC 2012

So I decided to add a pending_exception field to the thread object, but
it's already there!

mono_set_pending_exception sets the pending_exception field, but it looksit
is never called, ever... It looks very much like what I was intending on

It looks like it's partially implemented for AMD64 only - I propose
stripping the related calls from exceptions-amd64.c,
and have mono_thread_execute_interruption
return mono_thread_get_and_clear_pending_exception() somewhere near the end.

In the general case, native programs can just call
mono_set_pending_exception() if doesn't want to unwind right away.  In my
case, malloc can call it when memory gets low, and our equivalent of
SIGUSR1 can call it before calling


- Kipp
PS. thread->thread_interrupt_requested would need to be set
by mono_set_pending_exception.  mono_thread_notify_pending_exc_fn
and mono_threads_install_notify_pending_exc would need to be factored out.

On Wed, Feb 1, 2012 at 4:22 PM, Rodrigo Kumpera <kumpera at gmail.com> wrote:

> On Wed, Feb 1, 2012 at 1:39 PM, Miguel Mudge <michael.mudge at welchallyn.com
> > wrote:
>> On Wed, Feb 1, 2012 at 9:48 AM, Rodrigo Kumpera <kumpera at gmail.com>wrote:
>>> On Wed, Feb 1, 2012 at 12:22 PM, Miguel Mudge <
>>> michael.mudge at welchallyn.com> wrote:
>>>> 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.
>>> On which stack and thread is that function called? You obviously can't
>>> call it on the overflown one.
>> The RTOS is ThreadX for ARM - it is fairly useless.  Mono is supported
>> mostly by a homebrew POSIX implementation wrapped around it [cringe].
>> 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.
>>> The requirements are that:
>>>> - The native code is allowed to continue execution.
>>>> - The managed code throws a StackOverflowException that executes
>>>> finally blocks.
>>>> - The root AppDomain continues running.
>>>> 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?
>>> 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
>>>  well and this is something I would love to see patches for. Managed
>>> allocation failures are well handled with sgen.
>> 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.
>> 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.
>> 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.
>> 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.
> Now I see how and what you're trying to accomplish. Let's think in steps.
> 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
> then raising an OOM exception is sound.
> To apply it to stack overflow is a bit trickier since you need  to handle
> the case where managed code is executing as well.
> 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.
> 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.
> But would still need to patch the stack with a trampoline to raise the
> overflow exception in case it happens strictly on managed code.
> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ximian.com/pipermail/mono-devel-list/attachments/20120207/0c78d71f/attachment.html>

More information about the Mono-devel-list mailing list