Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/CodeGen/CodeGenerator.cc	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -133,8 +133,8 @@
 		output << "__attribute__ ((";
 		for ( list< Attribute * >::iterator attr( attributes.begin() );; ) {
-			output << (*attr)->get_name();
-			if ( ! (*attr)->get_parameters().empty() ) {
+			output << (*attr)->name;
+			if ( ! (*attr)->parameters.empty() ) {
 				output << "(";
-				genCommaList( (*attr)->get_parameters().begin(), (*attr)->get_parameters().end() );
+				genCommaList( (*attr)->parameters.begin(), (*attr)->parameters.end() );
 				output << ")";
 			} // if
@@ -836,4 +836,9 @@
 		assertf( ! genC, "Deleted expressions should not reach code generation." );
 		expr->expr->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( DefaultArgExpr * arg ) {
+		assertf( ! genC, "Default argument expressions should not reach code generation." );
+		arg->expr->accept( *visitor );
 	}
 
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/CodeGen/CodeGenerator.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -94,4 +94,5 @@
 		void postvisit( ConstructorExpr * );
 		void postvisit( DeletedExpr * );
+		void postvisit( DefaultArgExpr * );
 		void postvisit( GenericExpr * );
 
Index: src/Common/Debug.h
===================================================================
--- src/Common/Debug.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/Common/Debug.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -28,5 +28,5 @@
 namespace Debug {
 	/// debug codegen a translation unit
-	static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
+	static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Builtin ) {
 	#ifdef DEBUG
 		std::list< Declaration * > decls;
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/Common/PassVisitor.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -125,4 +125,5 @@
 	virtual void visit( InitExpr *  initExpr ) override final;
 	virtual void visit( DeletedExpr *  delExpr ) override final;
+	virtual void visit( DefaultArgExpr * argExpr ) override final;
 	virtual void visit( GenericExpr * genExpr ) override final;
 
@@ -224,4 +225,5 @@
 	virtual Expression * mutate( InitExpr *  initExpr ) override final;
 	virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
+	virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
 	virtual Expression * mutate( GenericExpr * genExpr ) override final;
 
@@ -258,4 +260,6 @@
 
 private:
+	bool inFunction = false;
+
 	template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
 	template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/Common/PassVisitor.impl.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -404,4 +404,8 @@
 			indexerAddId( &func );
 			maybeAccept_impl( node->type, *this );
+			// function body needs to have the same scope as parameters - CompoundStmt will not enter
+			// a new scope if inFunction is true
+			ValueGuard< bool > oldInFunction( inFunction );
+			inFunction = true;
 			maybeAccept_impl( node->statements, *this );
 			maybeAccept_impl( node->attributes, *this );
@@ -434,4 +438,8 @@
 			indexerAddId( &func );
 			maybeMutate_impl( node->type, *this );
+			// function body needs to have the same scope as parameters - CompoundStmt will not enter
+			// a new scope if inFunction is true
+			ValueGuard< bool > oldInFunction( inFunction );
+			inFunction = true;
 			maybeMutate_impl( node->statements, *this );
 			maybeMutate_impl( node->attributes, *this );
@@ -712,6 +720,9 @@
 	VISIT_START( node );
 	{
-		auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
+		ValueGuard< bool > oldInFunction( inFunction );
+		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
 		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
+		inFunction = false;
 		visitStatementList( node->kids );
 	}
@@ -723,6 +734,9 @@
 	MUTATE_START( node );
 	{
-		auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
+		ValueGuard< bool > oldInFunction( inFunction );
+		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
 		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
+		inFunction = false;
 		mutateStatementList( node->kids );
 	}
@@ -2084,4 +2098,27 @@
 
 //--------------------------------------------------------------------------
+// DefaultArgExpr
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( DefaultArgExpr * node ) {
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept_impl( node->expr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( DefaultArgExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env, *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutate_impl( node->expr, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
 // GenericExpr
 template< typename pass_type >
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/GenPoly/Lvalue.cc	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -146,16 +146,14 @@
 
 	namespace {
-		// true for intrinsic function calls that return a reference
+		// true for intrinsic function calls that return an lvalue in C
 		bool isIntrinsicReference( Expression * expr ) {
+			// known intrinsic-reference prelude functions
+			static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
 			if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
 				std::string fname = InitTweak::getFunctionName( untyped );
-				// known intrinsic-reference prelude functions
-				return fname == "*?" || fname == "?[?]";
+				return lvalueFunctions.count(fname);
 			} else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
 				if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
-					// use type of return variable rather than expr result type, since it may have been changed to a pointer type
-					FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
-					Type * ret = ftype->returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type();
-					return func->linkage == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
+					return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
 				}
 			}
@@ -212,5 +210,5 @@
 						// TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
 
-						if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
+						if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
 							// needed for definition of prelude functions, etc.
 							// if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
@@ -228,5 +226,5 @@
 							arg = new AddressExpr( arg );
 						// } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
-						} else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
+						} else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
 							// argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
 							PRINT(
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -176,8 +176,18 @@
 						selected[ mangleName ] = current;
 					} else if ( candidate->cost == mapPlace->second.candidate->cost ) {
-						PRINT(
-							std::cerr << "marking ambiguous" << std::endl;
-						)
-						mapPlace->second.isAmbiguous = true;
+						// if one of the candidates contains a deleted identifier, can pick the other, since
+						// deleted expressions should not be ambiguous if there is another option that is at least as good
+						if ( findDeletedExpr( candidate->expr ) ) {
+							// do nothing
+							PRINT( std::cerr << "candidate is deleted" << std::endl; )
+						} else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
+							PRINT( std::cerr << "current is deleted" << std::endl; )
+							selected[ mangleName ] = current;
+						} else {
+							PRINT(
+								std::cerr << "marking ambiguous" << std::endl;
+							)
+							mapPlace->second.isAmbiguous = true;
+						}
 					} else {
 						PRINT(
@@ -335,22 +345,9 @@
 		if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
 			// get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
-			// xxx - this should be improved by memoizing the value of constant exprs
-			// during parsing and reusing that information here.
-			std::stringstream ss( constantExpr->get_constant()->get_value() );
-			int val = 0;
+			auto val = constantExpr->intValue();
 			std::string tmp;
-			if ( ss >> val && ! (ss >> tmp) ) {
-				if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
-					alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
-				} // if
+			if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
+				alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
 			} // if
-		} else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
-			// xxx - temporary hack until 0/1 are int constants
-			if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
-				std::stringstream ss( nameExpr->get_name() );
-				int val;
-				ss >> val;
-				alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
-			}
 		} // if
 	}
@@ -439,4 +436,11 @@
 					return Cost::infinity;
 				}
+			}
+			if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
+				// default arguments should be free - don't include conversion cost.
+				// Unwrap them here because they are not relevant to the rest of the system.
+				*actualExpr = def->expr;
+				++formal;
+				continue;
 			}
 			Type * formalType = (*formal)->get_type();
@@ -611,6 +615,8 @@
 	ConstantExpr* getDefaultValue( Initializer* init ) {
 		if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
-			if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
-				return dynamic_cast<ConstantExpr*>( ce->get_arg() );
+			if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
+				return dynamic_cast<ConstantExpr*>( ce->arg );
+			} else {
+				return dynamic_cast<ConstantExpr*>( si->value );
 			}
 		}
@@ -873,5 +879,5 @@
 								indexer ) ) {
 							results.emplace_back(
-								i, cnstExpr, move(env), move(need), move(have),
+								i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
 								move(openVars), nextArg, nTuples );
 						}
@@ -1065,4 +1071,5 @@
 		funcFinder.findWithAdjustment( untypedExpr->function );
 		// if there are no function alternatives, then proceeding is a waste of time.
+		// xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
 		if ( funcFinder.alternatives.empty() ) return;
 
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/ResolvExpr/Resolver.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -36,4 +36,6 @@
 	void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
 	void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
+	/// Searches expr and returns the first DeletedExpr found, otherwise nullptr
+	DeletedExpr * findDeletedExpr( Expression * expr );
 } // namespace ResolvExpr
 
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/SymTab/Indexer.cc	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -126,5 +126,5 @@
 				decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
 				existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
-				if ( isUserDefinedFunc && ! data.deleteStmt ) {
+				if ( isUserDefinedFunc && ! deleteStmt ) {
 					// any user-defined function can act as an implicit delete statement for generated constructors.
 					// a delete stmt should not act as an implicit delete statement.
@@ -166,9 +166,19 @@
 				bool isCopyFunc = ball.isCopyFunc;
 				bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc;
-				// only implicitly delete non-user defined functions that are  not intrinsic, and are
-				// not copy functions (assignment or copy constructor), unless a user-defined copy function exists.
-				// deleteStmt will be non-null only if a user-defined function is found.
-				if (isNotUserDefinedFunc && (! isCopyFunc || existsUserDefinedCopyFunc)) {
-					ball.decl.deleteStmt = val.deleteStmt;
+
+				// only implicitly delete non-user defined functions that are not intrinsic, and are
+				// not copy functions (assignment or copy constructor). If a  user-defined copy function exists,
+				// do not pass along the non-user-defined copy functions since signatures do not have to match,
+				// and the generated functions will often be cheaper.
+				if ( isNotUserDefinedFunc ) {
+					if ( isCopyFunc ) {
+						// Skip over non-user-defined copy functions when there is a user-defined copy function.
+						// Since their signatures do not have to be exact, deleting them is the wrong choice.
+						if ( existsUserDefinedCopyFunc ) continue;
+					} else {
+						// delete non-user-defined non-copy functions if applicable.
+						// deleteStmt will be non-null only if a user-defined function is found.
+						ball.decl.deleteStmt = val.deleteStmt;
+					}
 				}
 				out.push_back( ball.decl );
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/SynTree/Expression.cc	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -746,4 +746,19 @@
 	os << std::endl << indent+1 << "... deleted by: ";
 	deleteStmt->print( os, indent+1 );
+}
+
+
+DefaultArgExpr::DefaultArgExpr( Expression * expr ) : expr( expr ) {
+	assert( expr->result );
+	result = expr->result->clone();
+}
+DefaultArgExpr::DefaultArgExpr( const DefaultArgExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ) {}
+DefaultArgExpr::~DefaultArgExpr() {
+	delete expr;
+}
+
+void DefaultArgExpr::print( std::ostream & os, Indenter indent ) const {
+	os << "Default Argument Expression" << std::endl << indent+1;
+	expr->print( os, indent+1 );
 }
 
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/SynTree/Expression.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -865,4 +865,19 @@
 };
 
+/// expression wrapping the use of a default argument - should never make it past the resolver.
+class DefaultArgExpr : public Expression {
+public:
+	Expression * expr;
+
+	DefaultArgExpr( Expression * expr );
+	DefaultArgExpr( const DefaultArgExpr & other );
+	~DefaultArgExpr();
+
+	virtual DefaultArgExpr * clone() const { return new DefaultArgExpr( * this ); }
+	virtual void accept( Visitor & v ) { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+};
+
 /// C11 _Generic expression
 class GenericExpr : public Expression {
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/SynTree/Mutator.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -93,4 +93,5 @@
 	virtual Expression * mutate( InitExpr  * initExpr ) = 0;
 	virtual Expression * mutate( DeletedExpr * delExpr ) = 0;
+	virtual Expression * mutate( DefaultArgExpr * argExpr ) = 0;
 	virtual Expression * mutate( GenericExpr * genExpr ) = 0;
 
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/SynTree/SynTree.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -101,4 +101,5 @@
 class InitExpr;
 class DeletedExpr;
+class DefaultArgExpr;
 class GenericExpr;
 
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/SynTree/Visitor.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -95,4 +95,5 @@
 	virtual void visit( InitExpr *  initExpr ) = 0;
 	virtual void visit( DeletedExpr * delExpr ) = 0;
+	virtual void visit( DefaultArgExpr * argExpr ) = 0;
 	virtual void visit( GenericExpr * genExpr ) = 0;
 
Index: src/tests/.gitignore
===================================================================
--- src/tests/.gitignore	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/.gitignore	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -1,2 +1,3 @@
 .out/
 .err/
+.type
Index: src/tests/Makefile.am
===================================================================
--- src/tests/Makefile.am	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/Makefile.am	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -28,5 +28,5 @@
 DEBUG_FLAGS =
 
-BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@
+BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -I.
 if !BUILD_DEBUG
 BUILD_FLAGS += -nodebug
Index: src/tests/Makefile.in
===================================================================
--- src/tests/Makefile.in	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/Makefile.in	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -309,5 +309,5 @@
 # applies to both programs
 DEBUG_FLAGS = 
-BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ \
+BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -I. \
 	$(am__append_1) $(am__append_2) $(am__append_3)
 TEST_FLAGS = $(if $(test), 2> $(test), )
Index: src/tests/concurrent/coroutineYield.c
===================================================================
--- src/tests/concurrent/coroutineYield.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/concurrent/coroutineYield.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -4,4 +4,7 @@
 #include <thread>
 #include <time>
+
+#define __kick_rate 150000ul
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -13,5 +16,5 @@
 }
 
-#ifdef LONG_TEST
+#ifdef TEST_LONG
 static const unsigned long N = 600_000ul;
 #else
@@ -23,7 +26,11 @@
 void main(Coroutine& this) {
 	while(true) {
-		sout | "Coroutine 1" | endl;
+		#if !defined(TEST_FOREVER)
+			sout | "Coroutine 1" | endl;
+		#endif
 		yield();
-		sout | "Coroutine 2" | endl;
+		#if !defined(TEST_FOREVER)
+			sout | "Coroutine 2" | endl;
+		#endif
 		suspend();
 	}
@@ -33,9 +40,14 @@
 int main(int argc, char* argv[]) {
 	Coroutine c;
-	for(int i = 0; i < N; i++) {
-		sout | "Thread 1" | endl;
+	for(int i = 0; TEST(i < N); i++) {
+		#if !defined(TEST_FOREVER)
+			sout | "Thread 1" | endl;
+		#endif
 		resume(c);
-		sout | "Thread 2" | endl;
+		#if !defined(TEST_FOREVER)
+			sout | "Thread 2" | endl;
+		#endif
 		yield();
+		KICK_WATCHDOG;
 	}
 }
Index: src/tests/concurrent/preempt.c
===================================================================
--- src/tests/concurrent/preempt.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/concurrent/preempt.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -2,4 +2,6 @@
 #include <thread>
 #include <time>
+
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -11,5 +13,5 @@
 }
 
-#ifdef LONG_TEST
+#ifdef TEST_LONG
 static const unsigned long N = 30_000ul;
 #else
@@ -30,5 +32,5 @@
 
 void main(worker_t & this) {
-	while(counter < N) {
+	while(TEST(counter < N)) {
 		__cfaabi_check_preemption();
 		if( (counter % 7) == this.value ) {
@@ -40,4 +42,5 @@
 		}
 		__cfaabi_check_preemption();
+		KICK_WATCHDOG;
 	}
 }
Index: src/tests/concurrent/signal/block.c
===================================================================
--- src/tests/concurrent/signal/block.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/concurrent/signal/block.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -14,4 +14,6 @@
 #include <time>
 
+#include "long_tests.h"
+
 #ifndef PREEMPTION_RATE
 #define PREEMPTION_RATE 10`ms
@@ -22,5 +24,5 @@
 }
 
-#ifdef LONG_TEST
+#ifdef TEST_LONG
 static const unsigned long N = 150_000ul;
 #else
@@ -66,6 +68,7 @@
 thread Waiter {};
 void main( Waiter & this ) {
-	for( int i = 0; i < N; i++ ) {
+	for( int i = 0; TEST(i < N); i++ ) {
 		wait_op( globalA, globalB, i );
+		KICK_WATCHDOG;
 	}
 }
Index: src/tests/concurrent/signal/disjoint.c
===================================================================
--- src/tests/concurrent/signal/disjoint.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/concurrent/signal/disjoint.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -4,4 +4,6 @@
 #include <thread>
 #include <time>
+
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -13,5 +15,5 @@
 }
 
-#ifdef LONG_TEST
+#ifdef TEST_LONG
 static const unsigned long N = 300_000ul;
 #else
@@ -67,9 +69,10 @@
 	}
 
-	d.counter++;
+	#if !defined(TEST_FOREVER)
+		d.counter++;
+		if( (d.counter % 1000) == 0 ) sout | d.counter | endl;
+	#endif
 
-	if( (d.counter % 1000) == 0 ) sout | d.counter | endl;
-
-	return d.counter < N;
+	return TEST(d.counter < N);
 }
 
@@ -77,5 +80,5 @@
 
 void main( Waiter & this ) {
-	while( wait( mut, data ) ) { yield(); }
+	while( wait( mut, data ) ) { KICK_WATCHDOG; yield(); }
 }
 
@@ -94,5 +97,5 @@
 
 	//This is technically a mutual exclusion violation but the mutex monitor protects us
-	bool running = data.counter < N && data.counter > 0;
+	bool running = TEST(data.counter < N) && data.counter > 0;
 	if( data.state != SIGNAL && running ) {
 		sout | "ERROR Eager signal" | data.state | endl;
Index: src/tests/concurrent/signal/wait.c
===================================================================
--- src/tests/concurrent/signal/wait.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/concurrent/signal/wait.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -12,4 +12,7 @@
 #include <time>
 
+#define __kick_rate 12000ul
+#include "long_tests.h"
+
 #ifndef PREEMPTION_RATE
 #define PREEMPTION_RATE 10`ms
@@ -20,5 +23,5 @@
 }
 
-#ifdef LONG_TEST
+#ifdef TEST_LONG
 static const unsigned long N = 375_000ul;
 #else
@@ -90,6 +93,7 @@
 // Waiter ABC
 void main( WaiterABC & this ) {
-	for( int i = 0; i < N; i++ ) {
+	for( int i = 0; TEST(i < N); i++ ) {
 		wait( condABC, globalA, globalB, globalC );
+		KICK_WATCHDOG;
 	}
 
@@ -100,6 +104,7 @@
 // Waiter AB
 void main( WaiterAB & this ) {
-	for( int i = 0; i < N; i++ ) {
+	for( int i = 0; TEST(i < N); i++ ) {
 		wait( condAB , globalA, globalB );
+		KICK_WATCHDOG;
 	}
 
@@ -110,6 +115,7 @@
 // Waiter AC
 void main( WaiterAC & this ) {
-	for( int i = 0; i < N; i++ ) {
+	for( int i = 0; TEST(i < N); i++ ) {
 		wait( condAC , globalA, globalC );
+		KICK_WATCHDOG;
 	}
 
@@ -120,6 +126,7 @@
 // Waiter BC
 void main( WaiterBC & this ) {
-	for( int i = 0; i < N; i++ ) {
+	for( int i = 0; TEST(i < N); i++ ) {
 		wait( condBC , globalB, globalC );
+		KICK_WATCHDOG;
 	}
 
Index: src/tests/long_tests.h
===================================================================
--- src/tests/long_tests.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
+++ src/tests/long_tests.h	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <unistd.h>
+
+#if   defined(TEST_FOREVER)
+
+static unsigned long long __kick_count = 0;
+#if !defined(__kick_rate)
+#define __kick_rate 5000ul
+#endif
+
+#define TEST(x) 1
+#define KICK_WATCHDOG do { __kick_count++; if(__kick_count > __kick_rate) { write(STDOUT_FILENO, ".", 1); __kick_count = 0; } } while(0)
+
+
+#else
+
+#define TEST(x) x
+#define KICK_WATCHDOG
+
+#endif
Index: src/tests/preempt_longrun/Makefile.am
===================================================================
--- src/tests/preempt_longrun/Makefile.am	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/Makefile.am	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -19,9 +19,16 @@
 preempt=10ul\`ms
 debug=-debug
+type=LONG
 
 REPEAT = ${abs_top_srcdir}/tools/repeat
+WATCHDOG = ${abs_top_srcdir}/tools/watchdog
 TIME = /usr/bin/time -f "%E"
 
-BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -DLONG_TEST
+# $(shell ./update-type $(type))
+# ./update-type $(type)
+
+UPDATED_TYPE = $(shell ./update-type $(type))
+
+BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -I.. -I. -DTEST_$(shell cat .type | tr a-z A-Z)
 CFLAGS = ${BUILD_FLAGS}
 CC = @CFA_BINDIR@/@CFA_NAME@
@@ -29,16 +36,30 @@
 TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
 
-.INTERMEDIATE: ${TESTS}
+# .INTERMEDIATE: ${TESTS}
 
 all-local: ${TESTS:=.run}
 
+runall : ${TESTS:=.run}
+	@ echo "All programs terminated normally"
+
+watchall : ${TESTS:=.watch}
+	@ echo "All programs terminated normally"
+
+compileall : ${TESTS}
+	@ echo "Compiled"
+
 clean-local:
-	rm -f ${TESTS} core* out.log
+	rm -f ${TESTS} core* out.log .type
 
-% : %.c ${CC}
+% : %.c ${CC} ${UPDATED_TYPE}
 	${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
 
 %.run : % ${REPEAT}
 	@ time ${REPEAT} -r out.log -i -s $(repeats) timeout ${max_time} ./${<}
+	@ rm ${<}
+	@ echo -e "${<}: SUCCESS\n"
+
+%.watch : % ${WATCHDOG}
+	@ time ${WATCHDOG} ./${<}
 	@ rm ${<}
 	@ echo -e "${<}: SUCCESS\n"
@@ -49,4 +70,7 @@
 	@ echo -e "${<}: SUCCESS\n"
 
-${REPEAT}:
+${REPEAT}: ${abs_top_srcdir}/tools/Makefile
 	@+make -C ${abs_top_srcdir}/tools/
+
+${WATCHDOG}: ${abs_top_srcdir}/tools/Makefile
+	@+make -C ${abs_top_srcdir}/tools/
Index: src/tests/preempt_longrun/Makefile.in
===================================================================
--- src/tests/preempt_longrun/Makefile.in	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/Makefile.in	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -452,7 +452,13 @@
 preempt = 10ul\`ms
 debug = -debug
+type = LONG
 REPEAT = ${abs_top_srcdir}/tools/repeat
+WATCHDOG = ${abs_top_srcdir}/tools/watchdog
 TIME = /usr/bin/time -f "%E"
-BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -DLONG_TEST
+
+# $(shell ./update-type $(type))
+# ./update-type $(type)
+UPDATED_TYPE = $(shell ./update-type $(type))
+BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -I.. -I. -DTEST_$(shell cat .type | tr a-z A-Z)
 TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
 all: all-am
@@ -873,12 +879,21 @@
 
 
-.INTERMEDIATE: ${TESTS}
+# .INTERMEDIATE: ${TESTS}
 
 all-local: ${TESTS:=.run}
 
+runall : ${TESTS:=.run}
+	@ echo "All programs terminated normally"
+
+watchall : ${TESTS:=.watch}
+	@ echo "All programs terminated normally"
+
+compileall : ${TESTS}
+	@ echo "Compiled"
+
 clean-local:
-	rm -f ${TESTS} core* out.log
-
-% : %.c ${CC}
+	rm -f ${TESTS} core* out.log .type
+
+% : %.c ${CC} ${UPDATED_TYPE}
 	${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
 
@@ -888,4 +903,9 @@
 	@ echo -e "${<}: SUCCESS\n"
 
+%.watch : % ${WATCHDOG}
+	@ time ${WATCHDOG} ./${<}
+	@ rm ${<}
+	@ echo -e "${<}: SUCCESS\n"
+
 %.time : % ${REPEAT}
 	@ ${REPEAT} -i -s -- $(repeats) $(TIME) -a -o times.log ./${<}
@@ -893,5 +913,8 @@
 	@ echo -e "${<}: SUCCESS\n"
 
-${REPEAT}:
+${REPEAT}: ${abs_top_srcdir}/tools/Makefile
+	@+make -C ${abs_top_srcdir}/tools/
+
+${WATCHDOG}: ${abs_top_srcdir}/tools/Makefile
 	@+make -C ${abs_top_srcdir}/tools/
 
Index: src/tests/preempt_longrun/create.c
===================================================================
--- src/tests/preempt_longrun/create.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/create.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -2,4 +2,6 @@
 #include <thread>
 #include <time>
+
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -19,6 +21,7 @@
 int main(int argc, char* argv[]) {
 	processor p;
-	for(int i = 0; i < N; i++) {
+	for(int i = 0; TEST(i < N); i++) {
 		worker_t w[7];
+		KICK_WATCHDOG;
 	}
 }
Index: src/tests/preempt_longrun/enter.c
===================================================================
--- src/tests/preempt_longrun/enter.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/enter.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -3,4 +3,7 @@
 #include <thread>
 #include <time>
+
+#define __kick_rate 75000ul
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -15,10 +18,12 @@
 
 monitor mon_t {};
-void foo( mon_t & mutex this ) {}
+void foo( mon_t & mutex this ) {
+	KICK_WATCHDOG;
+}
 
 mon_t mon;
 thread worker_t {};
 void main( worker_t & this ) {
-	for( unsigned long i = 0; i < N; i++ ) {
+	for( unsigned long i = 0; TEST(i < N); i++ ) {
 		foo( mon );
 	}
Index: src/tests/preempt_longrun/enter3.c
===================================================================
--- src/tests/preempt_longrun/enter3.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/enter3.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -3,4 +3,7 @@
 #include <thread>
 #include <time>
+
+#define __kick_rate 75000ul
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -18,10 +21,12 @@
 mon_t mon1, mon2, mon3;
 
-void foo( mon_t & mutex a, mon_t & mutex b, mon_t & mutex c ) {}
+void foo( mon_t & mutex a, mon_t & mutex b, mon_t & mutex c ) {
+	KICK_WATCHDOG;
+}
 
 thread worker_t {};
 
 void main( worker_t & this ) {
-	for( unsigned long i = 0; i < N; i++ ) {
+	for( unsigned long i = 0; TEST(i < N); i++ ) {
 		foo( mon1, mon2, mon3 );
 	}
Index: src/tests/preempt_longrun/processor.c
===================================================================
--- src/tests/preempt_longrun/processor.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/processor.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -4,4 +4,6 @@
 
 #include <unistd.h>
+
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -17,18 +19,15 @@
 int main(int argc, char* argv[]) {
 	processor * p[15];
-	write(STDOUT_FILENO, "Preparing\n", sizeof("Preparing\n"));
 	for ( int pi = 0; pi < 15; pi++ ) {
 		p[pi] = new();
 	}
-	write(STDOUT_FILENO, "Starting\n", sizeof("Starting\n"));
-	for ( int i = 0; i < N; i++) {
+	for ( int i = 0; TEST(i < N); i++) {
 		int pi = i % 15;
 		delete( p[pi] );
 		p[pi] = new();
+		KICK_WATCHDOG;
 	}
-	write(STDOUT_FILENO, "Stopping\n", sizeof("Stopping\n"));
 	for ( int pi = 0; pi < 15; pi++ ) {
 		delete( p[pi] );
 	}
-	write(STDOUT_FILENO, "Done\n", sizeof("Done\n"));
 }
Index: src/tests/preempt_longrun/stack.c
===================================================================
--- src/tests/preempt_longrun/stack.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/stack.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -3,4 +3,7 @@
 #include <thread>
 #include <time>
+
+#define __kick_rate 5000000ul
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -15,14 +18,17 @@
 
 void main(worker_t & this) {
-	volatile long long p = 5_021_609ul;
-	volatile long long a = 326_417ul;
-	volatile long long n = 1l;
-	for (volatile long long i = 0; i < p; i++) {
-		n *= a;
-		n %= p;
-	}
+	while(TEST(0)) {
+		volatile long long p = 5_021_609ul;
+		volatile long long a = 326_417ul;
+		volatile long long n = 1l;
+		for (volatile long long i = 0; i < p; i++) {
+			n *= a;
+			n %= p;
+			KICK_WATCHDOG;
+		}
 
-	if( n != a ) {
-		abort();
+		if( !TEST(n == a) ) {
+			abort();
+		}
 	}
 }
Index: src/tests/preempt_longrun/update-type
===================================================================
--- src/tests/preempt_longrun/update-type	(revision db4062dfc7318190a553c7282339cf3047457f17)
+++ src/tests/preempt_longrun/update-type	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+if [ "$#" -ne 1 ]
+then
+	echo "illegal number of parameters, must be 1 was $#"
+	exit
+fi
+
+NEW="$(echo $1 | tr a-z A-Z)"
+TYPE_FILE=".type"
+if [ -f "$TYPE_FILE" ]
+then
+	OLD="$(cat $TYPE_FILE | tr a-z A-Z)"
+	if [ $OLD == $NEW ]
+	then
+		echo > /dev/null
+		# echo "$TYPE_FILE stayed unchanged"
+	else
+		echo "$NEW" > "$TYPE_FILE"
+		# echo "$TYPE_FILE changed from '$OLD' to '$NEW'"
+	fi
+else
+	echo "$NEW" > "$TYPE_FILE"
+fi
+echo "$TYPE_FILE"
Index: src/tests/preempt_longrun/yield.c
===================================================================
--- src/tests/preempt_longrun/yield.c	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ src/tests/preempt_longrun/yield.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -2,4 +2,7 @@
 #include <thread>
 #include <time>
+
+#define __kick_rate 550000ul
+#include "long_tests.h"
 
 #ifndef PREEMPTION_RATE
@@ -11,5 +14,5 @@
 }
 
-#ifdef LONG_TEST
+#ifdef TEST_LONG
 static const unsigned long N = 9_750_000ul;
 #else
@@ -20,6 +23,7 @@
 
 void main(worker_t & this) {
-	for(int i = 0; i < N; i++) {
+	for(int i = 0; TEST(i < N); i++) {
 		yield();
+		KICK_WATCHDOG;
 	}
 }
Index: tools/Makefile.am
===================================================================
--- tools/Makefile.am	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ tools/Makefile.am	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -18,5 +18,5 @@
 CFLAGS = -Wall -Wextra -O2 -g
 
-noinst_PROGRAMS = busy catchsig repeat
+noinst_PROGRAMS = busy catchsig repeat watchdog
 
 busy_SOURCES     = busy.c
@@ -24,2 +24,3 @@
 catchsig_SOURCES = catchsig.c
 repeat_SOURCES   = repeat.c
+watchdog_SOURCES = watchdog.c
Index: tools/Makefile.in
===================================================================
--- tools/Makefile.in	(revision e04aec4e705020aa2c15b21c11c741bda20cc7f3)
+++ tools/Makefile.in	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -92,5 +92,6 @@
 build_triplet = @build@
 host_triplet = @host@
-noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT)
+noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT) \
+	watchdog$(EXEEXT)
 subdir = tools
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -115,4 +116,7 @@
 repeat_OBJECTS = $(am_repeat_OBJECTS)
 repeat_LDADD = $(LDADD)
+am_watchdog_OBJECTS = watchdog.$(OBJEXT)
+watchdog_OBJECTS = $(am_watchdog_OBJECTS)
+watchdog_LDADD = $(LDADD)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -143,6 +147,8 @@
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
-DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
+SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
+	$(watchdog_SOURCES)
+DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
+	$(watchdog_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
@@ -295,4 +301,5 @@
 catchsig_SOURCES = catchsig.c
 repeat_SOURCES = repeat.c
+watchdog_SOURCES = watchdog.c
 all: all-am
 
@@ -344,4 +351,8 @@
 	$(AM_V_CCLD)$(LINK) $(repeat_OBJECTS) $(repeat_LDADD) $(LIBS)
 
+watchdog$(EXEEXT): $(watchdog_OBJECTS) $(watchdog_DEPENDENCIES) $(EXTRA_watchdog_DEPENDENCIES) 
+	@rm -f watchdog$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(watchdog_OBJECTS) $(watchdog_LDADD) $(LIBS)
+
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -353,4 +364,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/catchsig.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repeat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watchdog.Po@am__quote@
 
 .c.o:
Index: tools/error.c
===================================================================
--- tools/error.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
+++ tools/error.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -0,0 +1,10 @@
+#include <signal.h>
+#include <unistd.h>
+
+int main() {
+	// while(1);
+	sleep(2);
+	// raise(SIGABRT);
+	raise(SIGSEGV);
+	return 0;
+}
Index: tools/watchdog.c
===================================================================
--- tools/watchdog.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
+++ tools/watchdog.c	(revision db4062dfc7318190a553c7282339cf3047457f17)
@@ -0,0 +1,175 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+char * this_cmd = NULL;
+
+void parse_args(int argc, char * argv[]);
+int run();
+void printcmd();
+
+int main(int argc, char * argv[]) {
+	parse_args(argc, argv);
+
+	int retcode = run();
+	if( !WIFEXITED(retcode) ) {
+		printf("Child Error : %d ", retcode); printcmd();
+		return retcode;
+	}
+
+	printf("Child exited normally "); printcmd();
+	return 0;
+}
+
+void usage( FILE * out, int code ) {
+	fprintf(out, "%s [OPTION] [--] N CMD\n", this_cmd);
+	fprintf(out, "Run command, killing it if it doesn't print for more than 5 continuous seconds\n\n");
+	fprintf(out, "\t-h,--help\tprint this usage message\n");
+	exit(code);
+}
+
+char ** cmd_to_run = NULL;
+pid_t child_pid = 0;
+int pipe_fds[2];
+
+void arg_error(void) {
+	fprintf(stderr,"\n");
+	usage(stderr, 1);
+}
+
+void parse_args(int argc, char * argv[]) {
+	this_cmd = argv[0];
+
+	enum { Help, };
+	static struct option long_opts[] = {
+		{ "help", no_argument, 0, Help },
+		{ 0, 0, 0, 0 }
+	}; // long_opts
+	int long_index;
+
+	int c;
+	while ( (c = getopt_long( argc, argv, "h", long_opts, &long_index)) != -1 ) {
+		switch ( c ) {
+			case Help:
+			case 'h':
+				usage(stdout, 0);
+				break;
+			default:
+				arg_error();
+				break;
+		} // switch
+	} // while
+
+	if( argc < optind + 1 ) {
+		fprintf(stderr, "Too few arguments\n");
+		arg_error();
+	}
+
+	cmd_to_run = argv + optind;
+}
+
+static void exit_handler (__attribute__((unused)) int a, __attribute__((unused)) void * b) {
+	close(pipe_fds[0]);
+	if(child_pid != 0) kill(child_pid, SIGKILL);
+}
+
+#define checked(call, ...) ({int ret = call(__VA_ARGS__); if (ret == -1) { perror(#call); exit(1); } ret;})
+
+void run_child();
+void make_noblock(int fd);
+void sink(int fd);
+int waitfd(int fd);
+
+int run() {
+	on_exit(exit_handler, NULL);
+	checked(pipe, pipe_fds);
+
+	printf("Watching command: "); printcmd();
+
+	child_pid = checked(fork);
+	if (child_pid == 0) { run_child(); }
+
+	close(pipe_fds[1]);
+	make_noblock(pipe_fds[0]);
+
+	int status;
+	while(waitpid(child_pid, &status, WNOHANG) == 0) {
+		if(waitfd(pipe_fds[0]) == 0) {
+			printf("Child Deadlocked "); printcmd();
+			exit(127);
+		}
+		sink(pipe_fds[0]);
+	}
+
+	child_pid = 0;
+	return status;
+
+	return 0;
+}
+
+void make_noblock(int fd) {
+	int flags = fcntl(fd, F_GETFL);
+	flags |= O_NONBLOCK;
+	fcntl(fd, F_SETFL, flags );
+}
+
+void sink(int fd) {
+	char buff[100];
+	int len = 100;
+	int rv;
+	do {
+		rv = read( fd, buff, len );
+	}
+	while(rv > 0);
+}
+
+int waitfd(int fd) {
+	fd_set set;
+	FD_ZERO(&set);
+	FD_SET(fd, &set);
+
+	struct timeval timeout;
+	timeout.tv_sec = 5;
+	timeout.tv_usec = 0;
+
+	int rv = select(fd + 1, &set, NULL, NULL, &timeout);
+	if(rv == -1) {
+		perror("select\n");
+		exit(1);
+	}
+	return rv;
+}
+
+void run_child() {
+	/* This is the child process. */
+	while ((dup2(pipe_fds[1], STDOUT_FILENO) == -1) && (errno == EINTR));
+
+	close(pipe_fds[1]);
+	close(pipe_fds[0]);
+
+	execvp ( *cmd_to_run, cmd_to_run);
+
+	/* The execvp  function returns only if an error occurs.  */
+	fprintf(stderr, "an error occurred in execvp\n");
+	abort ();
+}
+
+void printcmd() {
+	if(!cmd_to_run) return;
+	char ** cmd = cmd_to_run;
+	while (*cmd) {
+		printf("%s ", *cmd);
+		cmd++;
+	}
+	printf("\n");
+}
