Index: libcfa/src/concurrency/coroutine.cfa
===================================================================
--- libcfa/src/concurrency/coroutine.cfa	(revision d5f46131be643704ce63e4727b87001e3c5f3459)
+++ libcfa/src/concurrency/coroutine.cfa	(revision 4c868cb2d605f52664207c4a1a18ed9f041e2057)
@@ -47,4 +47,45 @@
 
 //-----------------------------------------------------------------------------
+FORALL_DATA_INSTANCE(CoroutineCancelled,
+		(dtype coroutine_t | sized(coroutine_t)), (coroutine_t))
+
+struct __cfaehm_node {
+	struct _Unwind_Exception unwind_exception;
+	struct __cfaehm_node * next;
+	int handler_index;
+};
+
+forall(dtype T)
+void mark_exception(CoroutineCancelled(T) *) {}
+
+forall(dtype T | sized(T))
+void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
+	dst->the_coroutine = src->the_coroutine;
+	dst->the_exception = src->the_exception;
+}
+
+forall(dtype T)
+const char * msg(CoroutineCancelled(T) *) {
+	return "CoroutineCancelled(...)";
+}
+
+// This code should not be inlined. It is the error path on resume.
+forall(dtype T | is_coroutine(T))
+void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) {
+	verify( desc->cancellation );
+	desc->state = Cancelled;
+	exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
+
+	CoroutineCancelled(T) except;
+	except.the_coroutine = &cor;
+	except.the_exception = except;
+	throwResume except;
+
+	except->virtual_table->free( except );
+	free( desc->cancellation );
+	desc->cancellation = 0p;
+}
+
+//-----------------------------------------------------------------------------
 // Global state variables
 
@@ -180,4 +221,6 @@
 	this->storage->limit = storage;
 	this->storage->base  = (void*)((intptr_t)storage + size);
+	this->storage->exception_context.top_resume = 0p;
+	this->storage->exception_context.current_exception = 0p;
 	__attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage;
 	*istorage |= userStack ? 0x1 : 0x0;
Index: libcfa/src/concurrency/coroutine.hfa
===================================================================
--- libcfa/src/concurrency/coroutine.hfa	(revision d5f46131be643704ce63e4727b87001e3c5f3459)
+++ libcfa/src/concurrency/coroutine.hfa	(revision 4c868cb2d605f52664207c4a1a18ed9f041e2057)
@@ -18,4 +18,23 @@
 #include <assert.h>
 #include "invoke.h"
+#include "../exception.hfa"
+
+//-----------------------------------------------------------------------------
+// Exception thrown from resume when a coroutine stack is cancelled.
+// Should not have to be be sized (see trac #196).
+FORALL_DATA_EXCEPTION(CoroutineCancelled,
+		(dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) (
+	coroutine_t * the_coroutine;
+	exception_t * the_exception;
+);
+
+forall(dtype T)
+void mark_exception(CoroutineCancelled(T) *);
+
+forall(dtype T | sized(T))
+void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src);
+
+forall(dtype T)
+const char * msg(CoroutineCancelled(T) *);
 
 //-----------------------------------------------------------------------------
@@ -23,7 +42,9 @@
 // Anything that implements this trait can be resumed.
 // Anything that is resumed is a coroutine.
-trait is_coroutine(dtype T) {
-      void main(T & this);
-      $coroutine * get_coroutine(T & this);
+trait is_coroutine(dtype T | sized(T)
+		| is_resumption_exception(CoroutineCancelled(T))
+		| VTABLE_ASSERTION(CoroutineCancelled, (T))) {
+	void main(T & this);
+	$coroutine * get_coroutine(T & this);
 };
 
@@ -112,4 +133,7 @@
 	}
 }
+
+forall(dtype T | is_coroutine(T))
+void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc );
 
 // Resume implementation inlined for performance
@@ -145,4 +169,7 @@
 	// always done for performance testing
 	$ctx_switch( src, dst );
+	if ( unlikely(dst->cancellation) ) {
+		__cfaehm_cancelled_coroutine( cor, dst );
+	}
 
 	return cor;
Index: libcfa/src/concurrency/exception.cfa
===================================================================
--- libcfa/src/concurrency/exception.cfa	(revision d5f46131be643704ce63e4727b87001e3c5f3459)
+++ libcfa/src/concurrency/exception.cfa	(revision 4c868cb2d605f52664207c4a1a18ed9f041e2057)
@@ -57,5 +57,8 @@
 
 STOP_AT_END_FUNCTION(coroutine_cancelstop,
-	// TODO: Instead pass information to the last resumer.
+	struct $coroutine * src = ($coroutine *)stop_param;
+	struct $coroutine * dst = src->last;
+
+	$ctx_switch( src, dst );
 	abort();
 )
Index: libcfa/src/concurrency/exception.hfa
===================================================================
--- libcfa/src/concurrency/exception.hfa	(revision d5f46131be643704ce63e4727b87001e3c5f3459)
+++ libcfa/src/concurrency/exception.hfa	(revision 4c868cb2d605f52664207c4a1a18ed9f041e2057)
@@ -18,11 +18,11 @@
 #include "bits/defs.hfa"
 #include "invoke.h"
-struct _Unwind_Exception;
-
-// It must also be usable as a C header file.
 
 #ifdef __cforall
 extern "C" {
+
+#define HIDE_EXPORTS
 #endif
+#include "unwind.h"
 
 struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD;
@@ -32,4 +32,5 @@
 
 #ifdef __cforall
+#undef HIDE_EXPORTS
 }
 #endif
Index: libcfa/src/concurrency/invoke.h
===================================================================
--- libcfa/src/concurrency/invoke.h	(revision d5f46131be643704ce63e4727b87001e3c5f3459)
+++ libcfa/src/concurrency/invoke.h	(revision 4c868cb2d605f52664207c4a1a18ed9f041e2057)
@@ -68,5 +68,5 @@
 	};
 
-	enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active };
+	enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled };
 
 	struct $coroutine {
