Skip to content

Commit be7a4ab

Browse files
Fix source debugger error handling: continue executing when detached (#1725)
Change main thread hangs when encounter debugger encounters error to main thread exits when debugger encounters error Change main thread blocks when debugger detaches to main thread continues executing when debugger detaches, and main thread exits normally when finishing executing
1 parent 12bcc20 commit be7a4ab

File tree

3 files changed

+96
-13
lines changed

3 files changed

+96
-13
lines changed

core/iwasm/libraries/debug-engine/debug_engine.c

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,23 @@ on_thread_stop_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env)
3636
os_mutex_unlock(&debug_inst->wait_lock);
3737
}
3838

39+
void
40+
on_thread_exit_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env)
41+
{
42+
os_mutex_lock(&debug_inst->wait_lock);
43+
44+
/* DBG_LAUNCHING: exit when debugger detached,
45+
* DBG_ERROR: exit when debugger error */
46+
if (debug_inst->current_state != DBG_LAUNCHING
47+
&& debug_inst->current_state != DBG_ERROR) {
48+
/* only when exit normally the debugger thread will participate in
49+
* teardown phase */
50+
debug_inst->stopped_thread = exec_env;
51+
}
52+
53+
os_mutex_unlock(&debug_inst->wait_lock);
54+
}
55+
3956
static WASMDebugEngine *g_debug_engine;
4057

4158
static uint32 current_instance_id = 1;
@@ -123,18 +140,20 @@ control_thread_routine(void *arg)
123140

124141
if (!wasm_gdbserver_listen(control_thread->server)) {
125142
LOG_ERROR("Failed while listening for debugger\n");
126-
return NULL;
143+
goto fail;
127144
}
128145

129146
/* outer infinite loop: try to connect with the debugger */
130147
while (true) {
131148
/* wait lldb client to connect */
132149
if (!wasm_gdbserver_accept(control_thread->server)) {
133150
LOG_ERROR("Failed while accepting debugger connection\n");
134-
return NULL;
151+
goto fail;
135152
}
136153

137154
control_thread->status = RUNNING;
155+
/* when reattached, send signal */
156+
wasm_cluster_send_signal_all(debug_inst->cluster, WAMR_SIG_SINGSTEP);
138157

139158
/* inner infinite loop: keep serving until detach */
140159
while (true) {
@@ -187,9 +206,9 @@ control_thread_routine(void *arg)
187206
/* Processing incoming requests */
188207
if (!wasm_gdbserver_handle_packet(control_thread->server)) {
189208
control_thread->status = STOPPED;
190-
LOG_VERBOSE("control thread of debug object [%p] stopped\n",
191-
debug_inst);
192-
wasm_close_gdbserver(control_thread->server);
209+
LOG_ERROR("An error occurs when handling a packet\n");
210+
os_mutex_unlock(&control_thread->wait_lock);
211+
goto fail;
193212
}
194213
}
195214
else if (is_thread_detached(control_thread)) {
@@ -203,6 +222,11 @@ control_thread_routine(void *arg)
203222
os_mutex_unlock(&control_thread->wait_lock);
204223
}
205224
}
225+
fail:
226+
wasm_debug_instance_on_failure(debug_inst);
227+
LOG_VERBOSE("control thread of debug object [%p] stopped with failure\n",
228+
debug_inst);
229+
return NULL;
206230
}
207231

208232
static WASMDebugControlThread *
@@ -971,6 +995,44 @@ wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
971995
return true;
972996
}
973997

998+
bool
999+
wasm_debug_instance_on_failure(WASMDebugInstance *instance)
1000+
{
1001+
WASMExecEnv *exec_env;
1002+
1003+
if (!instance)
1004+
return false;
1005+
1006+
os_mutex_lock(&instance->wait_lock);
1007+
exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
1008+
if (!exec_env) {
1009+
os_mutex_unlock(&instance->wait_lock);
1010+
return false;
1011+
}
1012+
1013+
if (instance->stopped_thread == NULL
1014+
&& instance->current_state == DBG_LAUNCHING) {
1015+
/* if fail in start stage: may need wait for main thread to notify it */
1016+
os_cond_wait(&instance->wait_cond, &instance->wait_lock);
1017+
}
1018+
instance->current_state = DBG_ERROR;
1019+
instance->stopped_thread = NULL;
1020+
1021+
/* terminate the wasm execution thread */
1022+
while (exec_env) {
1023+
/* Resume all threads so they can receive the TERM signal */
1024+
os_mutex_lock(&exec_env->wait_lock);
1025+
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
1026+
exec_env->current_status->running_status = STATUS_RUNNING;
1027+
os_cond_signal(&exec_env->wait_cond);
1028+
os_mutex_unlock(&exec_env->wait_lock);
1029+
exec_env = bh_list_elem_next(exec_env);
1030+
}
1031+
os_mutex_unlock(&instance->wait_lock);
1032+
1033+
return true;
1034+
}
1035+
9741036
bool
9751037
wasm_debug_instance_continue(WASMDebugInstance *instance)
9761038
{
@@ -1034,17 +1096,15 @@ wasm_debug_instance_detach(WASMDebugInstance *instance)
10341096
while (exec_env) {
10351097
if (instance->current_state == APP_STOPPED) {
10361098
/* Resume all threads since remote debugger detached*/
1037-
os_mutex_lock(&exec_env->wait_lock);
1038-
exec_env->current_status->running_status = STATUS_RUNNING;
1039-
os_cond_signal(&exec_env->wait_cond);
1040-
os_mutex_unlock(&exec_env->wait_lock);
1099+
wasm_cluster_thread_continue(exec_env);
10411100
}
10421101
exec_env = bh_list_elem_next(exec_env);
10431102
}
10441103

10451104
/* relaunch, accept new debug connection */
10461105
instance->current_state = DBG_LAUNCHING;
10471106
instance->control_thread->status = DETACHED;
1107+
instance->stopped_thread = NULL;
10481108

10491109
return true;
10501110
}

core/iwasm/libraries/debug-engine/debug_engine.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ typedef enum debug_state_t {
4242
*/
4343
DBG_LAUNCHING,
4444
APP_RUNNING,
45-
APP_STOPPED
45+
APP_STOPPED,
46+
DBG_ERROR
4647
} debug_state_t;
4748

4849
typedef struct WASMDebugExecutionMemory {
@@ -108,6 +109,9 @@ typedef enum WasmAddressType {
108109
void
109110
on_thread_stop_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env);
110111

112+
void
113+
on_thread_exit_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env);
114+
111115
WASMDebugInstance *
112116
wasm_debug_instance_create(WASMCluster *cluster, int32 port);
113117

@@ -180,6 +184,9 @@ bool
180184
wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
181185
uint64 length);
182186

187+
bool
188+
wasm_debug_instance_on_failure(WASMDebugInstance *instance);
189+
183190
bool
184191
wasm_debug_instance_interrupt_all_threads(WASMDebugInstance *instance);
185192

core/iwasm/libraries/thread-mgr/thread_manager.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,9 @@ wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
293293
other threads can't fire stop events */
294294
os_mutex_lock(&cluster->debug_inst->wait_lock);
295295
while (cluster->debug_inst->stopped_thread == exec_env) {
296-
os_cond_wait(&cluster->debug_inst->wait_cond,
297-
&cluster->debug_inst->wait_lock);
296+
/* either wakes up by signal or by 1-second timeout */
297+
os_cond_reltimedwait(&cluster->debug_inst->wait_cond,
298+
&cluster->debug_inst->wait_lock, 1000000);
298299
}
299300
os_mutex_unlock(&cluster->debug_inst->wait_lock);
300301
}
@@ -593,6 +594,21 @@ notify_debug_instance(WASMExecEnv *exec_env)
593594
on_thread_stop_event(cluster->debug_inst, exec_env);
594595
}
595596

597+
static void
598+
notify_debug_instance_exit(WASMExecEnv *exec_env)
599+
{
600+
WASMCluster *cluster;
601+
602+
cluster = wasm_exec_env_get_cluster(exec_env);
603+
bh_assert(cluster);
604+
605+
if (!cluster->debug_inst) {
606+
return;
607+
}
608+
609+
on_thread_exit_event(cluster->debug_inst, exec_env);
610+
}
611+
596612
void
597613
wasm_cluster_thread_stopped(WASMExecEnv *exec_env)
598614
{
@@ -624,7 +640,7 @@ void
624640
wasm_cluster_thread_exited(WASMExecEnv *exec_env)
625641
{
626642
exec_env->current_status->running_status = STATUS_EXIT;
627-
notify_debug_instance(exec_env);
643+
notify_debug_instance_exit(exec_env);
628644
}
629645

630646
void

0 commit comments

Comments
 (0)