Skip to content
Browse files

Thread doc

svn path=/trunk/mono/; revision=12307
  • Loading branch information...
1 parent d8a85c6 commit 5388febb0d0ef576dc96b44a70ace27f9b08a76c @dickp dickp committed
Showing with 156 additions and 0 deletions.
  1. +156 −0 docs/threading
View
156 docs/threading
@@ -0,0 +1,156 @@
+
+Threading in Mono
+=================
+
+ 0. Terminology
+ --------------
+
+ "Main thread" - The initial OS-native thread that the
+ application started with.
+
+ "Helper thread" - A native thread created internally
+ by the runtime, such as the finalizer thread, or an
+ asynchronous delegate invocation thread. These
+ threads can run managed code.
+
+ "Primary CLR thread" - The native thread that called
+ the Main() method when executing an assembly.
+
+ "Secondary CLR thread" - A native thread created by a
+ program that instantiates a System.Threading.Thread object
+ and calls its Start() method.
+
+ 1. Thread exit behaviour in the standalone mono runtime
+ -------------------------------------------------------
+
+ The correct behaviour of the runtime should be:
+
+ a) If Main() returns, the runtime should wait for all
+ foreground secondary CLR threads to finish. The
+ wording in the class documentation states: "Once all
+ foreground threads belonging to a process have
+ terminated, the common language runtime ends the
+ process by invoking Abort on any background threads
+ that are still alive." Testing seems to indicate that
+ the background thread can't cancel the Abort by
+ catching the ThreadAbortException and calling
+ ResetAbort here. Indeed, not even the finally block
+ seems to be executed.
+
+ b) if any of the primary CLR thread, a secondary CLR
+ thread or a helper thread calls
+ System.Environment.Exit(), the application should
+ terminate immediately without waiting for foreground
+ primary or secondary CLR threads to finish.
+
+ c) if the primary CLR thread throws an uncaught
+ exception, the application should terminate
+ immediately without waiting for secondary CLR threads
+ to finish. This might be implemented internally by
+ pretending that all the running secondary CLR threads
+ are background threads.
+
+ d) if a secondary CLR thread throws an uncaught
+ exception that thread should terminate and all other
+ threads should continue to execute.
+
+ e) if a helper thread throws an uncaught exception and
+ that thread happens to be the GC finalizer thread,
+ testing seems to indicate that the exception stack
+ trace is displayed as normal, and the exception is
+ then ignored (as though there is a try {} catch{}
+ around all finalizers that just prints the stack
+ trace.) Calling Abort() on the GC finalizer thread
+ also does not cause it to exit: it behaves as though
+ the ThreadAbortException is caught and ResetAbort is
+ called. Asynchronous delegate helper threads should
+ behave as secondary CLR threads, but uncaught
+ exceptions should be rethrown on the thread that calls
+ EndInvoke().
+
+
+ The difficulties happen with cases b) and c):
+
+ The current implementation of
+ System.Environment.Exit() calls exit(2) directly,
+ which is rather unfriendly: it prevents any runtime
+ cleanup, statistics gathering, etc. and is pretty
+ obnoxious to embedded code.
+
+ The current exception handling code calls ExitThread()
+ (emulated with pthread_exit() in the io-layer) if an
+ exception is not caught.
+
+ When called from the main thread, both POSIX
+ pthread_exit() and w32 ExitThread() block if there are
+ other threads still running (in the w32 case, if there
+ are other foreground threads still running; threads
+ can set as background.) If the main thread is also
+ the primary CLR thread, then the application will
+ block until all other threads (including helper
+ threads) terminate. Some helper threads will not
+ terminate until specifically told to by the runtime:
+ for example, the GC finalizer thread needs to run
+ until all of the primary and secondary CLR threads
+ have finished.
+
+ Also, if the main thread is also the primary CLR
+ thread, the runtime loses the opportunity to do any
+ cleaning up. Adding a special case to call exit(2)
+ instead of ExitThread() in the primary CLR thread
+ suffers from the same problems as
+ System.Environment.Exit() calling exit(2).
+
+
+ The simple solution is to run the primary CLR thread
+ in a new native thread, leaving the main thread free
+ for housekeeping duties. There still needs to be some
+ special handling for the case where the primary CLR
+ thread fails to catch an exception: the secondary CLR
+ threads then need to be terminated.
+
+ When the primary and secondary CLR threads have all
+ terminated, the helper threads can be killed off and
+ the runtime can clean itself up and exit.
+
+
+
+ 2. Thread initialisation
+ ------------------------
+
+ Threads have to undergo some initialisation before
+ managed code can be executed. A
+ System.Threading.Thread object must be created, and
+ the thread details need to be stored so that the
+ threads can be managed later. The JIT needs to record
+ the last managed frame stack pointer in a TLS slot,
+ and the current Thread object is also recorded.
+
+ New threads created by managed calls to
+ System.Threading.Thread methods will have all needed
+ initialisation performed. Threads created by the
+ runtime with calls to mono_thread_create() will too.
+ Existing threads can be passed to the runtime; these
+ must call mono_thread_attach() before any CLR code can
+ be executed on that thread.
+
+
+ 3. Constraints on embedding the Mono runtime
+ --------------------------------------------
+
+ The discussion above concerning application behaviour
+ in the event of threads terminating, whether by
+ returning from the start function, throwing uncaught
+ exceptions or by calling System.Environment.Exit(),
+ only really applies to the standalone Mono runtime.
+
+ An embedding application should specify what behaviour
+ is required when, for example,
+ System.Environment.Exit() is called. The application
+ is also responsible for its own thread management, and
+ it should be prepared for any of the primary CLR
+ thread or secondary CLR threads to terminate at any
+ time. The application should also take into account
+ that the runtime will create helper threads as needed,
+ as this may cause pthread_exit() or ExitThread() to
+ block indefinitely, as noted above.

0 comments on commit 5388feb

Please sign in to comment.
Something went wrong with that request. Please try again.