Index: benchmark/io/http/filecache.cfa
===================================================================
--- benchmark/io/http/filecache.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ benchmark/io/http/filecache.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -209,4 +209,9 @@
 
 [int *, int] filefds(int extra) {
+	if(!options.file_cache.path) {
+		int * data = alloc(extra);
+		return [data, 0];
+	}
+
 	if(!file_cache.entries) {
 		abort("File cache not filled!\n");
Index: benchmark/io/http/main.cfa
===================================================================
--- benchmark/io/http/main.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ benchmark/io/http/main.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -80,10 +80,12 @@
 	//===================
 	// Parse args
-	const char * path = parse_options(argc, argv);
+	parse_options(argc, argv);
 
 	//===================
 	// Open Files
-	sout | "Filling cache from" | path;
-	fill_cache( path );
+	if( options.file_cache.path ) {
+		sout | "Filling cache from" | options.file_cache.path;
+		fill_cache( options.file_cache.path );
+	}
 
 	//===================
@@ -147,5 +149,5 @@
 		}
 
-		if(options.file_cache.fixed_fds) {
+		if(options.file_cache.path && options.file_cache.fixed_fds) {
 			register_fixed_files(cl, fds, pipe_off);
 		}
@@ -184,34 +186,40 @@
 				}
 
-				sout | "Notifying connections";
+				sout | "Notifying connections..." | nonl; flush( sout );
 				for(i; options.clopts.nworkers) {
 					workers[i].done = true;
 					cancel(workers[i].cancel);
 				}
-
-				sout | "Shutting down socket";
+				sout | "done";
+
+				sout | "Shutting down socket..." | nonl; flush( sout );
 				int ret = shutdown( server_fd, SHUT_RD );
-				if( ret < 0 ) { abort( "shutdown error: (%d) %s\n", (int)errno, strerror(errno) ); }
+				if( ret < 0 ) {
+					abort( "shutdown error: (%d) %s\n", (int)errno, strerror(errno) );
+				}
+				sout | "done";
 
 				//===================
 				// Close Socket
-				sout | "Closing Socket";
+				sout | "Closing Socket..." | nonl; flush( sout );
 				ret = close( server_fd );
 				if(ret < 0) {
 					abort( "close socket error: (%d) %s\n", (int)errno, strerror(errno) );
 				}
-				sout | "Stopping connection threads..." | nonl;
+				sout | "done";
+
+				sout | "Stopping connection threads..." | nonl; flush( sout );
 			}
 			sout | "done";
 
-			sout | "Stopping protocol threads..." | nonl;
+			sout | "Stopping protocol threads..." | nonl; flush( sout );
 			deinit_protocol();
 			sout | "done";
 
-			sout | "Stopping processors..." | nonl;
+			sout | "Stopping processors..." | nonl; flush( sout );
 		}
 		sout | "done";
 
-		sout | "Closing splice fds..." | nonl;
+		sout | "Closing splice fds..." | nonl; flush( sout );
 		for(i; pipe_cnt) {
 			ret = close( fds[pipe_off + i] );
@@ -223,5 +231,5 @@
 		sout | "done";
 
-		sout | "Stopping processors..." | nonl;
+		sout | "Stopping processors..." | nonl; flush( sout );
 	}
 	sout | "done";
@@ -229,6 +237,8 @@
 	//===================
 	// Close Files
-	sout | "Closing open files..." | nonl;
-	close_cache();
-	sout | "done";
-}
+	if( options.file_cache.path ) {
+		sout | "Closing open files..." | nonl; flush( sout );
+		close_cache();
+		sout | "done";
+	}
+}
Index: benchmark/io/http/options.cfa
===================================================================
--- benchmark/io/http/options.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ benchmark/io/http/options.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -9,7 +9,9 @@
 }
 
+#include <fstream.hfa>
 #include <kernel.hfa>
 #include <parseargs.hfa>
 
+#include <stdlib.h>
 #include <string.h>
 
@@ -18,4 +20,5 @@
 
 	{ // file_cache
+		0,     // path
 		0,     // open_flags;
 		42u,   // hash_seed;
@@ -34,5 +37,5 @@
 		1,     // nprocs;
 		1,     // nworkers;
-		0,     // flags;
+		{},     // params;
 		false, // procstats
 		false, // viewhalts
@@ -41,5 +44,5 @@
 };
 
-const char * parse_options( int argc, char * argv[] ) {
+void parse_options( int argc, char * argv[] ) {
 	bool subthrd = false;
 	bool eagrsub = false;
@@ -97,7 +100,8 @@
 
 	if( left[0] != 0p ) {
-		abort("Too many trailing arguments!\n");
+		serr | "Too many trailing arguments!";
+		exit(EXIT_FAILURE);
 	}
 
-	return path;
+	options.file_cache.path = path;
 }
Index: benchmark/io/http/options.hfa
===================================================================
--- benchmark/io/http/options.hfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ benchmark/io/http/options.hfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -11,4 +11,5 @@
 
 	struct {
+		const char * path;
 		int open_flags;
 		uint32_t hash_seed;
@@ -36,3 +37,3 @@
 extern Options options;
 
-const char * parse_options( int argc, char * argv[] );
+void parse_options( int argc, char * argv[] );
Index: benchmark/io/http/protocol.cfa
===================================================================
--- benchmark/io/http/protocol.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ benchmark/io/http/protocol.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -26,4 +26,5 @@
 	"HTTP/1.1 400 Bad Request\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n",
 	"HTTP/1.1 404 Not Found\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n",
+	"HTTP/1.1 405 Method Not Allowed\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n",
 	"HTTP/1.1 408 Request Timeout\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n",
 	"HTTP/1.1 413 Payload Too Large\nServer: HttoForall\nDate: %s \nContent-Type: text/plain\nContent-Length: 0 \n\n",
@@ -37,4 +38,5 @@
 	400,
 	404,
+	405,
 	408,
 	413,
@@ -104,4 +106,5 @@
 			if( errno == EAGAIN || errno == EWOULDBLOCK) continue READ;
 			if( errno == ECONNRESET ) return [E408, true, 0, 0];
+			if( errno == EPIPE ) return [E408, true, 0, 0];
 			abort( "read error: (%d) %s\n", (int)errno, strerror(errno) );
 		}
Index: benchmark/io/http/protocol.hfa
===================================================================
--- benchmark/io/http/protocol.hfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ benchmark/io/http/protocol.hfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -7,4 +7,5 @@
 	E400,
 	E404,
+	E405,
 	E408,
 	E413,
Index: benchmark/io/http/worker.cfa
===================================================================
--- benchmark/io/http/worker.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ benchmark/io/http/worker.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -97,4 +97,14 @@
 			}
 
+			if( !options.file_cache.path ) {
+				if( options.log ) {
+					sout | "=== File Not Found (" | nonl;
+					write(sout, file, name_size);
+					sout | ") ===";
+				}
+				answer_error(fd, E405);
+				continue REQUEST;
+			}
+
 			// Get the fd from the file cache
 			int ans_fd;
@@ -104,7 +114,9 @@
 			// If we can't find the file, return 404
 			if( ans_fd < 0 ) {
-				sout | "=== File Not Found (" | nonl;
-				write(sout, file, name_size);
-				sout | ") ===";
+				if( options.log ) {
+					sout | "=== File Not Found (" | nonl;
+					write(sout, file, name_size);
+					sout | ") ===";
+				}
 				answer_error(fd, E404);
 				continue REQUEST;
Index: libcfa/src/concurrency/io.cfa
===================================================================
--- libcfa/src/concurrency/io.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ libcfa/src/concurrency/io.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -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 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ libcfa/src/concurrency/io/setup.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -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 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ libcfa/src/concurrency/io/types.hfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -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 );
Index: libcfa/src/concurrency/kernel.cfa
===================================================================
--- libcfa/src/concurrency/kernel.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ libcfa/src/concurrency/kernel.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -633,5 +633,5 @@
 	// abort cannot be recursively entered by the same or different processors because all signal handlers return when
 	// the globalAbort flag is true.
-	bool first = __atomic_test_and_set( &kernel_abort_called, __ATOMIC_SEQ_CST);
+	bool first = !__atomic_test_and_set( &kernel_abort_called, __ATOMIC_SEQ_CST);
 
 	// first task to abort ?
Index: libcfa/src/concurrency/mutex.hfa
===================================================================
--- libcfa/src/concurrency/mutex.hfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ libcfa/src/concurrency/mutex.hfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -42,9 +42,9 @@
 };
 
-void ?{}(mutex_lock & this);
-void ^?{}(mutex_lock & this);
-void lock(mutex_lock & this);
-bool try_lock(mutex_lock & this);
-void unlock(mutex_lock & this);
+void ?{}(mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void ^?{}(mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void lock(mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+bool try_lock(mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void unlock(mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
 
 // Exclusive lock - recursive
@@ -64,9 +64,9 @@
 };
 
-void ?{}(recursive_mutex_lock & this);
-void ^?{}(recursive_mutex_lock & this);
-void lock(recursive_mutex_lock & this);
-bool try_lock(recursive_mutex_lock & this);
-void unlock(recursive_mutex_lock & this);
+void ?{}(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void ^?{}(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void lock(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+bool try_lock(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void unlock(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
 
 trait is_lock(dtype L | sized(L)) {
@@ -86,14 +86,14 @@
 };
 
-void ?{}(condition_variable & this);
-void ^?{}(condition_variable & this);
+void ?{}(condition_variable & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void ^?{}(condition_variable & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
 
-void notify_one(condition_variable & this);
-void notify_all(condition_variable & this);
+void notify_one(condition_variable & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
+void notify_all(condition_variable & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
 
-void wait(condition_variable & this);
+void wait(condition_variable & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
 
 forall(dtype L | is_lock(L))
-void wait(condition_variable & this, L & l);
+void wait(condition_variable & this, L & l) __attribute__((deprecated("use concurrency/locks.hfa instead")));
 
 //-----------------------------------------------------------------------------
Index: libcfa/src/parseargs.cfa
===================================================================
--- libcfa/src/parseargs.cfa	(revision 0cc43e1fadb39979645cb0d70447d7e7db2ee4c5)
+++ libcfa/src/parseargs.cfa	(revision 78a8440e1737d69aeee9685090a6aa319befc025)
@@ -148,5 +148,12 @@
 	if(hwidth <= 0) hwidth = max;
 
-	fprintf(out, "  -%c, --%-*s   %.*s\n", sn, width, ln, hwidth, help);
+	char sname[4] = { ' ', ' ', ' ', '\0' };
+	if(sn != '\0') {
+		sname[0] = '-';
+		sname[1] = sn;
+		sname[2] = ',';
+	}
+
+	fprintf(out, "  %s --%-*s   %.*s\n", sname, width, ln, hwidth, help);
 	for() {
 		help += min(strlen(help), hwidth);
