diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c
index 4a73ba504abbfa26bb8a945675cd5c14c8d8deae..18872ff6ebaccac4365f197c4a00eb82bebf1301 100644
--- a/src/slurmctld/controller.c
+++ b/src/slurmctld/controller.c
@@ -966,8 +966,7 @@ static void _slurm_rpc_job_step_kill(slurm_msg_t * msg)
 			   (long) (clock() - start_time));
 			slurm_send_rc_msg(msg, SLURM_SUCCESS);
 
-			/* Below functions provide their own locking */
-			schedule();
+			/* Below function provides its own locking */
 			(void) dump_all_job_state();
 
 		}
diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c
index 3915097c1a1854f9a71c6894cdd4a80f11649d38..cb10f0e4c635e2d3ff48d966519124f517000d70 100644
--- a/src/slurmctld/job_mgr.c
+++ b/src/slurmctld/job_mgr.c
@@ -458,16 +458,16 @@ static int _load_job_state(Buf buffer)
 		      job_id, job_state, batch_flag);
 		goto unpack_error;
 	}
-	if ((kill_on_node_fail > 1) || (kill_on_step_done > 1)) {
-		error("Invalid data for job %u: kill_on_node_fail=%u",
-		      job_id, kill_on_node_fail);
-		goto unpack_error;
-	}
-	if ((kill_on_node_fail > 1) || (kill_on_step_done > 1)) {
+	if (kill_on_step_done > KILL_IN_PROGRESS) {
 		error("Invalid data for job %u: kill_on_step_done=%u",
 		      job_id, kill_on_step_done);
 		goto unpack_error;
 	}
+	if (kill_on_node_fail > 1) {
+		error("Invalid data for job %u: kill_on_node_fail=%u",
+		      job_id, kill_on_node_fail);
+		goto unpack_error;
+	}
 	if ((nodes) && (node_name2bitmap(nodes, &node_bitmap))) {
 		error("_load_job_state: invalid nodes (%s) for job_id %u",
 		      nodes, job_id);
@@ -1113,6 +1113,7 @@ int job_allocate(job_desc_msg_t * job_specs, uint32_t * new_job_id,
 int job_signal(uint32_t job_id, uint16_t signal, uid_t uid)
 {
 	struct job_record *job_ptr;
+	time_t now = time(NULL);
 
 	job_ptr = find_job_record(job_id);
 	if (job_ptr == NULL) {
@@ -1122,7 +1123,8 @@ int job_signal(uint32_t job_id, uint16_t signal, uid_t uid)
 
 	if ((job_ptr->job_state == JOB_FAILED) ||
 	    (job_ptr->job_state == JOB_COMPLETE) ||
-	    (job_ptr->job_state == JOB_TIMEOUT))
+	    (job_ptr->job_state == JOB_TIMEOUT) ||
+	    (job_ptr->kill_on_step_done & KILL_IN_PROGRESS))
 		return ESLURM_ALREADY_DONE;
 
 	if ((job_ptr->user_id != uid) && (uid != 0) && (uid != getuid())) {
@@ -1133,7 +1135,7 @@ int job_signal(uint32_t job_id, uint16_t signal, uid_t uid)
 
 	if ((job_ptr->job_state == JOB_PENDING) &&
 	    (signal == SIGKILL)) {
-		last_job_update = time(NULL);
+		last_job_update = now;
 		job_ptr->job_state = JOB_FAILED;
 		job_ptr->start_time = job_ptr->end_time = time(NULL);
 		delete_job_details(job_ptr);
@@ -1155,14 +1157,16 @@ int job_signal(uint32_t job_id, uint16_t signal, uid_t uid)
 		}
 		list_iterator_destroy (step_record_iterator);
 
-		if (signal == SIGKILL) {
-			job_ptr->kill_on_step_done = 1;
-			last_job_update = time(NULL);
+		if ((signal == SIGKILL) &&
+		    ((job_ptr->kill_on_step_done & KILL_IN_PROGRESS) == 0)) {
+			job_ptr->kill_on_step_done = KILL_IN_PROGRESS;
+			job_ptr->time_last_active = now;
+			last_job_update = now;
 		}
 		if ((signal == SIGKILL) && (step_cnt == 0)) {
 			/* kill job with no active steps */
 			job_ptr->job_state = JOB_COMPLETE;
-			job_ptr->end_time = time(NULL);
+			job_ptr->end_time = now;
 			deallocate_nodes(job_ptr);
 			delete_job_details(job_ptr);
 		}
@@ -1190,6 +1194,7 @@ job_complete(uint32_t job_id, uid_t uid, bool requeue,
 	     uint32_t job_return_code)
 {
 	struct job_record *job_ptr;
+	time_t now = time(NULL);
 
 	job_ptr = find_job_record(job_id);
 	if (job_ptr == NULL) {
@@ -1224,13 +1229,15 @@ job_complete(uint32_t job_id, uid_t uid, bool requeue,
 	} else {
 		if (job_return_code)
 			job_ptr->job_state = JOB_FAILED;
+		else if (job_ptr->end_time < now)
+			job_ptr->job_state = JOB_TIMEOUT;
 		else
 			job_ptr->job_state = JOB_COMPLETE;
-		job_ptr->end_time = time(NULL);
+		job_ptr->end_time = now;
 		delete_job_details(job_ptr);
 		delete_all_step_records(job_ptr);
 	}
-	last_job_update = time(NULL);
+	last_job_update = now;
 	return SLURM_SUCCESS;
 }
 
@@ -1861,6 +1868,22 @@ void job_time_limit(void)
 		    (job_ptr->job_state == JOB_TIMEOUT) ||
 		    (job_ptr->job_state == JOB_NODE_FAIL))
 			continue;
+
+		if ((job_ptr->kill_on_step_done & KILL_IN_PROGRESS) &&
+		    (difftime(now, job_ptr->time_last_active) >
+		     JOB_KILL_TIMEOUT)) {
+			info("Job_id %u not properly terminating, forcing it",
+			     job_ptr->job_id);
+			last_job_update = now;
+			job_ptr->job_state = JOB_TIMEOUT;
+			job_ptr->end_time = time(NULL);
+			deallocate_nodes(job_ptr);
+			delete_all_step_records(job_ptr);
+			delete_job_details(job_ptr);
+		}
+		if (job_ptr->kill_on_step_done & KILL_IN_PROGRESS)
+			continue;
+
 		if (slurmctld_conf.inactive_limit) {
 			if (job_ptr->step_list &&
 			    (list_count(job_ptr->step_list) > 0))
@@ -1876,13 +1899,11 @@ void job_time_limit(void)
 		    (job_ptr->end_time > now))
 			continue;
 		last_job_update = now;
-		info("Time limit exhausted for job_id %u, terminated",
+		info("Time limit exhausted for job_id %u, terminating",
 		     job_ptr->job_id);
-		job_ptr->job_state = JOB_TIMEOUT;
-		job_ptr->end_time = time(NULL);
-		deallocate_nodes(job_ptr);
-		delete_all_step_records(job_ptr);
-		delete_job_details(job_ptr);
+		job_signal(job_ptr->job_id, SIGKILL, 0);
+		if (job_ptr->job_state == JOB_COMPLETE)
+			job_ptr->job_state = JOB_TIMEOUT;
 	}
 
 	list_iterator_destroy(job_record_iterator);
diff --git a/src/slurmctld/slurmctld.h b/src/slurmctld/slurmctld.h
index c8d8577bfd28736f0b7dcb2a1603f7678ef4a599..fb3315ed094acca7b4ce98e0eaefb63e5faf5f65 100644
--- a/src/slurmctld/slurmctld.h
+++ b/src/slurmctld/slurmctld.h
@@ -85,6 +85,10 @@
 /* Check for jobs reaching their time limit every PERIODIC_TIMEOUT seconds */
 #define	PERIODIC_TIMEOUT	60
 
+/* Release a job's allocation if it does not terminate gracefully in
+ * JOB_KILL_TIMEOUT seconds */
+#define	JOB_KILL_TIMEOUT	60
+
 /* Pathname of group file record for checking update times */
 #define GROUP_FILE	"/etc/group"
 
@@ -192,6 +196,8 @@ extern time_t last_job_update;	/* time of last update to part records */
 #define DETAILS_MAGIC 0xdea84e7
 #define JOB_MAGIC 0xf0b7392c
 #define STEP_MAGIC 0xce593bc1
+#define KILL_ON_STEP_DONE	1
+#define KILL_IN_PROGRESS	2
 
 extern int job_count;			/* number of jobs in the system */
 
@@ -234,7 +240,8 @@ struct job_record {
 	uint16_t kill_on_node_fail;	/* 1 if job should be killed on 
 					   node failure */
 	uint16_t kill_on_step_done;	/* 1 if job should be killed when 
-					   the job step completes */
+					   the job step completes, 2 if kill
+					   in progress */
 	char *nodes;			/*  list of nodes allocated to job */
 	bitstr_t *node_bitmap;		/* bitmap of nodes allocated to job */
 	uint32_t time_limit;		/* time_limit minutes or INFINITE */