diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 00de5fc6fe942b2ab7ac2b6bb5b80623f5da6f8a..ad09a0e704624a47d605b3d3afdf5a9174b062f2 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -2194,10 +2194,13 @@ int gdb_input_inner(connection_t *connection)
 				retval = target_halt(target);
 				if (retval != ERROR_OK)
 				{
-					/* stop this debug session */
 					target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
 				}
 				gdb_con->ctrl_c = 0;
+			} else
+			{
+				LOG_INFO("The target is not running when halt was requested, stopping GDB.");
+				target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
 			}
 		}
 
diff --git a/src/target/target.c b/src/target/target.c
index ced09e900966f36d2042868cdafcc47fd4e30b00..8bb9371f903bca836e16a17021668ac79dc8a21e 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -378,24 +378,57 @@ target_t* get_current_target(command_context_t *cmd_ctx)
 
 int target_poll(struct target_s *target)
 {
+	int retval;
+
 	/* We can't poll until after examine */
 	if (!target_was_examined(target))
 	{
 		/* Fail silently lest we pollute the log */
 		return ERROR_FAIL;
 	}
-	return target->type->poll(target);
+
+	retval = target->type->poll(target);
+	if (retval != ERROR_OK)
+		return retval;
+
+	if (target->halt_issued)
+	{
+		if (target->state == TARGET_HALTED)
+		{
+			target->halt_issued = false;
+		} else
+		{
+			long long t = timeval_ms() - target->halt_issued_time;
+			if (t>1000)
+			{
+				target->halt_issued = false;
+				LOG_INFO("Halt timed out, wake up GDB.");
+				target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
+			}
+		}
+	}
+
+	return ERROR_OK;
 }
 
 int target_halt(struct target_s *target)
 {
+	int retval;
 	/* We can't poll until after examine */
 	if (!target_was_examined(target))
 	{
 		LOG_ERROR("Target not examined yet");
 		return ERROR_FAIL;
 	}
-	return target->type->halt(target);
+
+	retval = target->type->halt(target);
+	if (retval != ERROR_OK)
+		return retval;
+
+	target->halt_issued = true;
+	target->halt_issued_time = timeval_ms();
+
+	return ERROR_OK;
 }
 
 int target_resume(struct target_s *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
@@ -4236,6 +4269,8 @@ static int target_create(Jim_GetOptInfo *goi)
 
 	target->display             = 1;
 
+	target->halt_issued			= false;
+
 	/* initialize trace information */
 	target->trace_info = malloc(sizeof(trace_t));
 	target->trace_info->num_trace_points         = 0;
diff --git a/src/target/target.h b/src/target/target.h
index 6547d4d782026c44219193e959d30c1b30cb5c64..0f8be6f2cbf56968a3a58547594d460a1477bbbf 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -148,6 +148,8 @@ typedef struct target_s
 
 	int display;						/* display async info in telnet session. Do not display
 										 * lots of halted/resumed info when stepping in debugger. */
+	bool halt_issued;					/* did we transition to halted state? */
+	long long halt_issued_time;			/* Note time when halt was issued */
 } target_t;
 
 enum target_event