[Mono-dev] [PATCH] New shutdown code

Mark Probst mark.probst at gmail.com
Thu Dec 13 09:14:55 EST 2007

Hi Paolo, Dick, and everybody else!

Here's the new shutdown code which should fix bugs #337383 and #347676.

We have two shutdown paths in Mono:

* Implicit exit: All threads shut down normally
* Explicit exit: Some thread calls System.Environment.Exit()

In implicit exit the main thread shuts Mono down.  In explicit exit
whichever thread executes Exit() shuts down Mono.

Problem: Two (or more) threads might attempt shutdown at the same time.
That's what mono_threads_set_shutting_down() is for: Make sure only one
thread gets to shut Mono down, the others just die or play dead.

Before shutting down Mono all threads must quit or must be suspended.
To avoid deadlock (two threads waiting for each other's suspension or
death, which can happen if the main thread is finished and waits for the
other threads and another thread wants to shut down via Exit) a thread
about to shut Mono down must set its status to finished (so that the
main thread will wake up from its waiting loop, realize that someone
wants to shut down, and get out of the game), and a thread wanting to
shut down, but failing (because another thread came first) must either
quit or pretend, as well.

This is what mono_threads_set_shutting_down() does, atomically (it
acquires the threads lock):

mono_threads_set_shutting_down (bool may_abort) {
  if (shutting_down) {
    // somebody else is already shutting down
    if (may_abort)
      call Thread.Abort() on self
    else {
      play dead;
  } else {
    shutting_down = TRUE;
    set self status to finished, but don't actually quit;

We make sure (via the threads lock) that no thread can start (although
they can still be created) after mono_threads_set_shutting_down() has
been called for the first time.

Here are the two shutdown paths:

Main thread, after Main() has exited:

do {
  wait for threads to change state;
  // some threads changed state
  if (somebody else is exiting)
    play dead;
} while (!all threads finished);
// all threads are finished now, but some threads might still start in 
// this window
// we're allowed to shut down, and no more threads can start now
abort all other threads;
shut down;

Some thread (could be main thread), from Exit():

// we're allowed to shut down, and no more threads can start now
suspend all other threads;
shut down;

Does the patch look ok?  Any cases I've missed?

-------------- next part --------------
A non-text attachment was scrubbed...
Name: shutdown.diff
Type: text/x-patch
Size: 8241 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20071213/94574adc/attachment.bin 

More information about the Mono-devel-list mailing list