Index: libcfa/src/concurrency/invoke.h
===================================================================
--- libcfa/src/concurrency/invoke.h	(revision 9d6e1b8ae1a5072ddee5a7fcfec69271df0f6430)
+++ libcfa/src/concurrency/invoke.h	(revision f9b2e7388420b253282b546bc3300f089e8d2b89)
@@ -68,5 +68,5 @@
 	};
 
-	enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled };
+	enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled, Halting };
 
 	struct $coroutine {
Index: libcfa/src/concurrency/kernel.cfa
===================================================================
--- libcfa/src/concurrency/kernel.cfa	(revision 9d6e1b8ae1a5072ddee5a7fcfec69271df0f6430)
+++ libcfa/src/concurrency/kernel.cfa	(revision f9b2e7388420b253282b546bc3300f089e8d2b89)
@@ -288,5 +288,5 @@
 		}
 
-		if(unlikely(thrd_dst->state == Halted)) {
+		if(unlikely(thrd_dst->state == Halting)) {
 			// The thread has halted, it should never be scheduled/run again
 			// finish the thread
@@ -484,5 +484,5 @@
 		/* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) < ((uintptr_t)__get_stack(thrd->curr_cor)->base ), "ERROR : $thread %p has been corrupted.\n StackPointer too small.\n", thrd );
 
-		thrd->state = Halted;
+		thrd->state = Halting;
 		if( TICKET_RUNNING != thrd->ticket ) { abort( "Thread terminated with pending unpark" ); }
 		if( thrd != this->owner ) { abort( "Thread internal monitor has incorrect owner" ); }
Index: libcfa/src/concurrency/monitor.cfa
===================================================================
--- libcfa/src/concurrency/monitor.cfa	(revision 9d6e1b8ae1a5072ddee5a7fcfec69271df0f6430)
+++ libcfa/src/concurrency/monitor.cfa	(revision f9b2e7388420b253282b546bc3300f089e8d2b89)
@@ -142,4 +142,7 @@
 static void __dtor_enter( $monitor * this, fptr_t func, bool join ) {
 	$thread * thrd = active_thread();
+	#if defined( __CFA_WITH_VERIFY__ )
+		bool is_thrd = this == &thrd->self_mon;
+	#endif
 
 	// Lock the monitor spinlock
@@ -155,5 +158,6 @@
 		__set_owner( this, thrd );
 
-		verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
+		/* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
+		/* paranoid */ verify( !is_thrd || thrd->state == Halted || thrd->state == Cancelled );
 
 		unlock( this->lock );
@@ -175,9 +179,13 @@
 		__set_owner( this, thrd );
 
-		verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
+		/* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
+		/* paranoid */ verify( !is_thrd || thrd->state == Halted || thrd->state == Cancelled );
 
 		unlock( this->lock );
 		return;
 	}
+
+	// The monitor is busy, if this is a thread and the thread owns itself, it better be active
+	/* paranoid */ verify( !is_thrd || this->owner != thrd || (thrd->state != Halted && thrd->state != Cancelled) );
 
 	__lock_size_t count = 1;
@@ -209,4 +217,7 @@
 		// Some one was waiting for us, enter
 		/* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
+
+		__cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
+		return;
 	}
 	else {
@@ -228,7 +239,4 @@
 		return;
 	}
-
-	__cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
-
 }
 
@@ -294,5 +302,5 @@
 
 	/* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
-	/* paranoid */ verify( thrd->state == Halted );
+	/* paranoid */ verify( thrd->state == Halting );
 	/* paranoid */ verify( this->recursion == 1 );
 
@@ -303,4 +311,7 @@
 	// Fetch the next thread, can be null
 	$thread * new_owner = next_thread( this );
+
+	// Mark the state as fully halted
+	thrd->state = Halted;
 
 	// Release the monitor lock
Index: libcfa/src/concurrency/thread.cfa
===================================================================
--- libcfa/src/concurrency/thread.cfa	(revision 9d6e1b8ae1a5072ddee5a7fcfec69271df0f6430)
+++ libcfa/src/concurrency/thread.cfa	(revision f9b2e7388420b253282b546bc3300f089e8d2b89)
@@ -82,10 +82,15 @@
 		T & thrd, void(*defaultResumptionHandler)(ThreadCancelled(T) &)) {
 	$monitor * m = get_monitor(thrd);
+	$thread * desc = get_thread(thrd);
+
+	// Setup the monitor guard
 	void (*dtor)(T& mutex this) = ^?{};
 	bool join = defaultResumptionHandler != (void(*)(ThreadCancelled(T)&))0;
 	(this.mg){&m, (void(*)())dtor, join};
 
+
+	/* paranoid */ verifyf( Halted == desc->state || Cancelled == desc->state, "Expected thread to be Halted or Cancelled, was %d\n", (int)desc->state );
+
 	// After the guard set-up and any wait, check for cancellation.
-	$thread * desc = get_thread(thrd);
 	struct _Unwind_Exception * cancellation = desc->self_cor.cancellation;
 	if ( likely( 0p == cancellation ) ) {
