Index: libcfa/src/concurrency/exception.cfa
===================================================================
--- libcfa/src/concurrency/exception.cfa	(revision 9b0c3ec5a87c40b085a2ec3ed4be75524987f899)
+++ libcfa/src/concurrency/exception.cfa	(revision ab8c6a6efe9f4120bf5d5eed0b649cad34d89af3)
@@ -19,4 +19,6 @@
 #include <unwind.h>
 #undef HIDE_EXPORTS
+
+extern void __cfactx_thrd_leave();
 }
 
@@ -52,6 +54,6 @@
 
 STOP_AT_END_FUNCTION(thread_cancelstop,
-	// TODO: Instead pass information to the joiner.
-	abort();
+    __cfactx_thrd_leave();
+    __cabi_abort( "Resumed cancelled thread" );
 )
 
@@ -85,4 +87,6 @@
 		stop_param = (void *)0x22;
 	} else {
+		this_thread->self_cor.cancellation = unwind_exception;
+
 		stop_func = thread_cancelstop;
 		stop_param = this_thread;
Index: libcfa/src/concurrency/monitor.cfa
===================================================================
--- libcfa/src/concurrency/monitor.cfa	(revision 9b0c3ec5a87c40b085a2ec3ed4be75524987f899)
+++ libcfa/src/concurrency/monitor.cfa	(revision ab8c6a6efe9f4120bf5d5eed0b649cad34d89af3)
@@ -306,15 +306,4 @@
 	/* paranoid */ verify( thrd->state == Halted );
 	unpark( new_owner );
-}
-
-// Join a thread
-forall( dtype T | is_thread(T) )
-T & join( T & this ) {
-	$monitor *    m = get_monitor(this);
-	void (*dtor)(T& mutex this) = ^?{};
-	monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
-	{
-		return this;
-	}
 }
 
Index: libcfa/src/concurrency/thread.cfa
===================================================================
--- libcfa/src/concurrency/thread.cfa	(revision 9b0c3ec5a87c40b085a2ec3ed4be75524987f899)
+++ libcfa/src/concurrency/thread.cfa	(revision ab8c6a6efe9f4120bf5d5eed0b649cad34d89af3)
@@ -19,4 +19,5 @@
 
 #include "kernel_private.hfa"
+#include "exception.hfa"
 
 #define __CFA_INVOKE_PRIVATE__
@@ -58,4 +59,65 @@
 }
 
+FORALL_DATA_INSTANCE(ThreadCancelled, (dtype thread_t), (thread_t))
+
+forall(dtype T)
+void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src) {
+	dst->virtual_table = src->virtual_table;
+	dst->the_thread = src->the_thread;
+	dst->the_exception = src->the_exception;
+}
+
+forall(dtype T)
+const char * msg(ThreadCancelled(T) *) {
+	return "ThreadCancelled";
+}
+
+struct __cfaehm_node {
+	struct _Unwind_Exception unwind_exception;
+	struct __cfaehm_node * next;
+	int handler_index;
+};
+
+forall(dtype T)
+static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
+	abort( "Unhandled thread cancellation.\n" );
+}
+
+forall(dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
+void ?{}( thread_dtor_guard_t & this,
+		T & thrd, void(*defaultResumptionHandler)(ThreadCancelled(T) &)) {
+	$monitor * m = get_monitor(thrd);
+	void (*dtor)(T& mutex this) = ^?{};
+	bool join = defaultResumptionHandler != (void(*)(ThreadCancelled(T)&))0;
+	(this.mg){&m, (void(*)())dtor, join};
+	{
+		$thread * desc = get_thread(thrd);
+		struct _Unwind_Exception * cancellation = desc->self_cor.cancellation;
+		if ( likely(0p == cancellation) ) {
+			return;
+		} else if ( Cancelled == desc->state ) {
+			return;
+		}
+		desc->state = Cancelled;
+		if (!join) {
+			defaultResumptionHandler = default_thread_cancel_handler;
+		}
+		ThreadCancelled(T) except;
+		// TODO: Remove explitate vtable set once trac#186 is fixed.
+		except.virtual_table = &get_exception_vtable(&except);
+		except.the_thread = &thrd;
+		except.the_exception = (exception_t *)(1 + (__cfaehm_node *)cancellation);
+		throwResume except;
+
+		except.the_exception->virtual_table->free( except.the_exception );
+		free( cancellation );
+		desc->self_cor.cancellation = 0p;
+	}
+}
+
+void ^?{}( thread_dtor_guard_t & this ) {
+	^(this.mg){};
+}
+
 //-----------------------------------------------------------------------------
 // Starting and stopping threads
@@ -93,4 +155,11 @@
 }
 
+//-----------------------------------------------------------------------------
+forall(dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
+T & join( T & this ) {
+	thread_dtor_guard_t guard = { this, defaultResumptionHandler };
+	return this;
+}
+
 // Local Variables: //
 // mode: c //
Index: libcfa/src/concurrency/thread.hfa
===================================================================
--- libcfa/src/concurrency/thread.hfa	(revision 9b0c3ec5a87c40b085a2ec3ed4be75524987f899)
+++ libcfa/src/concurrency/thread.hfa	(revision ab8c6a6efe9f4120bf5d5eed0b649cad34d89af3)
@@ -22,12 +22,24 @@
 #include "kernel.hfa"
 #include "monitor.hfa"
+#include "exception.hfa"
 
 //-----------------------------------------------------------------------------
 // thread trait
 trait is_thread(dtype T) {
-      void ^?{}(T& mutex this);
-      void main(T& this);
-      $thread* get_thread(T& this);
+	void ^?{}(T& mutex this);
+	void main(T& this);
+	$thread* get_thread(T& this);
 };
+
+FORALL_DATA_EXCEPTION(ThreadCancelled, (dtype thread_t), (thread_t)) (
+	thread_t * the_thread;
+	exception_t * the_exception;
+);
+
+forall(dtype T)
+void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src);
+
+forall(dtype T)
+const char * msg(ThreadCancelled(T) *);
 
 // define that satisfies the trait without using the thread keyword
@@ -65,4 +77,12 @@
 static inline void ?{}($thread & this, const char * const name, struct cluster & cl )                   { this{ name, cl, 0p, 65000 }; }
 static inline void ?{}($thread & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, 0p, stackSize }; }
+
+struct thread_dtor_guard_t {
+	monitor_dtor_guard_t mg;
+};
+
+forall( dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)) )
+void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(ThreadCancelled(T) &) );
+void ^?{}( thread_dtor_guard_t & this );
 
 //-----------------------------------------------------------------------------
@@ -108,5 +128,5 @@
 //----------
 // join
-forall( dtype T | is_thread(T) )
+forall( dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)) )
 T & join( T & this );
 
