Index: libcfa/src/concurrency/io.cfa
===================================================================
--- libcfa/src/concurrency/io.cfa	(revision 0edd11a6077a0ddf81da70d5c62e8928e3d3e1b8)
+++ libcfa/src/concurrency/io.cfa	(revision d61199552c4f8550ce4d335625d57b1e5aa16381)
@@ -318,4 +318,6 @@
 
 		__cfadbg_print_safe(io_core, "Kernel I/O : Fast poller %d (%p) stopping\n", this.ring->fd, &this);
+
+		__ioctx_unregister( this );
 	}
 
Index: libcfa/src/concurrency/io/setup.cfa
===================================================================
--- libcfa/src/concurrency/io/setup.cfa	(revision 0edd11a6077a0ddf81da70d5c62e8928e3d3e1b8)
+++ libcfa/src/concurrency/io/setup.cfa	(revision d61199552c4f8550ce4d335625d57b1e5aa16381)
@@ -113,8 +113,9 @@
 
 	static struct {
-		pthread_t     thrd;    // pthread handle to io poller thread
-		void *        stack;   // pthread stack for io poller thread
-		int           epollfd; // file descriptor to the epoll instance
-		volatile bool run;     // Whether or not to continue
+		pthread_t       thrd;    // pthread handle to io poller thread
+		void *          stack;   // pthread stack for io poller thread
+		int             epollfd; // file descriptor to the epoll instance
+		volatile bool   run;     // Whether or not to continue
+		volatile size_t epoch;   // Epoch used for memory reclamation
 	} iopoll;
 
@@ -131,4 +132,5 @@
 		iopoll.run = true;
 		iopoll.stack = __create_pthread( &iopoll.thrd, iopoll_loop, 0p );
+		iopoll.epoch = 0;
 	}
 
@@ -174,4 +176,7 @@
 		while( iopoll.run ) {
 			__cfadbg_print_safe(io_core, "Kernel I/O - epoll : waiting on io_uring contexts\n");
+
+			// increment the epoch to notify any deleters we are starting a new cycle
+			__atomic_fetch_add(&iopoll.epoch, 1, __ATOMIC_SEQ_CST);
 
 			// Wait for events
@@ -496,9 +501,7 @@
 // I/O Context Sleep
 //=============================================================================================
-	#define IOEVENTS EPOLLIN | EPOLLONESHOT
-
 	static inline void __ioctx_epoll_ctl($io_ctx_thread & ctx, int op, const char * error) {
 		struct epoll_event ev;
-		ev.events = IOEVENTS;
+		ev.events = EPOLLIN | EPOLLONESHOT;
 		ev.data.u64 = (__u64)&ctx;
 		int ret = epoll_ctl(iopoll.epollfd, op, ctx.ring->efd, &ev);
@@ -517,4 +520,23 @@
 	}
 
+	void __ioctx_unregister($io_ctx_thread & ctx) {
+		// Read the current epoch so we know when to stop
+		size_t curr = __atomic_load_n(&iopoll.epoch, __ATOMIC_SEQ_CST);
+
+		// Remove the fd from the iopoller
+		__ioctx_epoll_ctl(ctx, EPOLL_CTL_DEL, "REMOVE");
+
+		// Notify the io poller thread of the shutdown
+		iopoll.run = false;
+		sigval val = { 1 };
+		pthread_sigqueue( iopoll.thrd, SIGUSR1, val );
+
+		// Make sure all this is done
+		__atomic_thread_fence(__ATOMIC_SEQ_CST);
+
+		// Wait for the next epoch
+		while(curr == __atomic_load_n(&iopoll.epoch, __ATOMIC_RELAXED)) yield();
+	}
+
 //=============================================================================================
 // I/O Context Misc Setup
Index: libcfa/src/concurrency/io/types.hfa
===================================================================
--- libcfa/src/concurrency/io/types.hfa	(revision 0edd11a6077a0ddf81da70d5c62e8928e3d3e1b8)
+++ libcfa/src/concurrency/io/types.hfa	(revision d61199552c4f8550ce4d335625d57b1e5aa16381)
@@ -133,4 +133,5 @@
 	struct $io_ctx_thread;
 	void __ioctx_register($io_ctx_thread & ctx);
+	void __ioctx_unregister($io_ctx_thread & ctx);
 	void __ioctx_prepare_block($io_ctx_thread & ctx);
 	void __sqe_clean( volatile struct io_uring_sqe * sqe );
