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 adding. 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 mono_thread_current_check_pending_interrupt. Thoughts? - 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 <[email protected]> wrote: > > > On Wed, Feb 1, 2012 at 1:39 PM, Miguel Mudge <[email protected] > > wrote: > >> On Wed, Feb 1, 2012 at 9:48 AM, Rodrigo Kumpera <[email protected]>wrote: >> >>> On Wed, Feb 1, 2012 at 12:22 PM, Miguel Mudge < >>> [email protected]> 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. > > >
_______________________________________________ Mono-devel-list mailing list [email protected] http://lists.ximian.com/mailman/listinfo/mono-devel-list
