From d516b51063656c7cac01493f73d349860dc21c45 Mon Sep 17 00:00:00 2001 From: lightovernight <119399319+lightovernight@users.noreply.github.com> Date: Sat, 16 Aug 2025 20:04:59 +0800 Subject: [PATCH] Gsoc 2025 debugger (#387) * add debugger module * simplify the workdir process * Update main.c * Update main.c * update debugger * change port to 6110 * Update main.c * simplify the workdir process and minor optimizations * implement exit event * Fix memory management in setBreakpoints * replace free to PK_FREE * Add custom command ready --------- Co-authored-by: blueloveTH --- src/debugger/core.c | 4 ++-- src/debugger/dap.c | 47 ++++++++++++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/debugger/core.c b/src/debugger/core.c index 7d29f01d..021c9a07 100644 --- a/src/debugger/core.c +++ b/src/debugger/core.c @@ -47,7 +47,7 @@ inline static void init_structures() { c11_vector__ctor(&debugger.py_frames, sizeof(py_Frame*)); c11_smallmap_d2index__ctor(&debugger.scopes_query_cache); py_newlist(python_vars); - py_newnil(py_list_emplace(python_vars)); + py_newnone(py_list_emplace(python_vars)); } inline static void clear_structures() { @@ -91,7 +91,7 @@ C11_DEBUGGER_STATUS c11_debugger_on_trace(py_Frame* frame, enum py_TraceEvent ev case TRACE_EVENT_POP: debugger.curr_stack_depth--; break; default: break; } - if(debugger.curr_stack_depth == 0) return C11_DEBUGGER_EXIT; + // if(debugger.curr_stack_depth == 0) return C11_DEBUGGER_EXIT; return C11_DEBUGGER_SUCCESS; } diff --git a/src/debugger/dap.c b/src/debugger/dap.c index 608e0076..d97270e8 100644 --- a/src/debugger/dap.c +++ b/src/debugger/dap.c @@ -8,6 +8,7 @@ X(initialize) \ X(setBreakpoints) \ X(attach) \ + X(launch) \ X(next) \ X(stepIn) \ X(stepOut) \ @@ -16,7 +17,8 @@ X(scopes) \ X(variables) \ X(threads) \ - X(configurationDone) + X(configurationDone) \ + X(ready) #define DECLARE_HANDLE_FN(name) void c11_dap_handle_##name(py_Ref arguments, c11_sbuf*); DAP_COMMAND_LIST(DECLARE_HANDLE_FN) @@ -36,9 +38,6 @@ static dap_command_entry dap_command_table[] = { #undef DAP_ENTRY -// #undef DAP_COMMAND_LIST - -// static int dap_next_seq = 1; static struct c11_dap_server { int dap_next_seq; char buffer_data[1024]; @@ -48,6 +47,7 @@ static struct c11_dap_server { c11_socket_handler toclient; bool isconfiguredone; bool isatttach; + bool isclientready; } server; void c11_dap_handle_initialize(py_Ref arguments, c11_sbuf* buffer) { @@ -57,6 +57,10 @@ void c11_dap_handle_initialize(py_Ref arguments, c11_sbuf* buffer) { void c11_dap_handle_attach(py_Ref arguments, c11_sbuf* buffer) { server.isatttach = true; } +void c11_dap_handle_launch(py_Ref arguments, c11_sbuf* buffer) { server.isatttach = true; } + +void c11_dap_handle_ready(py_Ref arguments, c11_sbuf* buffer) {server.isclientready = true;} + void c11_dap_handle_next(py_Ref arguments, c11_sbuf* buffer) { c11_debugger_set_step_mode(C11_STEP_OVER); } @@ -154,7 +158,7 @@ void c11_dap_handle_variables(py_Ref arguments, c11_sbuf* buffer) { const char* c11_dap_handle_request(const char* message) { if(!py_json_loads(message)) { py_printexc(); - return NULL; + c11__abort("[DEBUGGER ERROR] invalid JSON request"); } py_Ref py_request = py_pushtmp(); py_Ref py_arguments = py_pushtmp(); @@ -222,14 +226,13 @@ void c11_dap_send_event(const char* event_name, const char* body_json) { char header[64]; int header_len = snprintf(header, sizeof(header), "Content-Length: %d\r\n\r\n", json_len); - + // printf("[DEBUGGER INFO] send event %s\n", json); c11_socket_send(server.toclient, header, header_len); c11_socket_send(server.toclient, json, json_len); } void c11_dap_send_stop_event() { - c11_dap_send_event("stopped", - "{\"threadId\":1,\"allThreadsStopped\":true}"); + c11_dap_send_event("stopped", "{\"threadId\":1,\"allThreadsStopped\":true}"); } void c11_dap_send_exited_event(int exitCode) { @@ -263,7 +266,7 @@ int c11_dap_read_content_length(const char* buffer, int* header_length) { char* endptr = NULL; long value = strtol(length_begin, &endptr, 10); if(endptr == length_begin) { - printf("[DEBUGGER EORRO] : the number is empty\n"); + printf("[DEBUGGER EORRO] : the length field is empty\n"); *header_length = 0; return -1; } @@ -321,16 +324,20 @@ void c11_dap_init_server(const char* hostname, unsigned short port) { server.isconfiguredone = false; server.buffer_begin = server.buffer_data; server.server = c11_socket_create(C11_AF_INET, C11_SOCK_STREAM, 0); + server.isclientready = false; c11_socket_bind(server.server, hostname, port); c11_socket_listen(server.server, 0); printf("[DEBUGGER INFO] : listen on %s:%hu\n", hostname, port); +} + +void c11_dap_waitforclient(const char* hostname, unsigned short port) { server.toclient = c11_socket_accept(server.server, NULL, NULL); - printf("[DEBUGGER INFO] : connected client\n"); + printf("[DEBUGGER INFO] : connected a client\n"); } inline static void c11_dap_handle_message() { const char* message = c11_dap_read_message(); - if(message == NULL) return; + if(message == NULL) { return; } // printf("[DEBUGGER INFO] read request %s\n", message); const char* response_content = c11_dap_handle_request(message); // if(response_content != NULL) { printf("[DEBUGGER INFO] send response %s\n", response_content); } @@ -350,6 +357,9 @@ void c11_dap_configure_debugger() { if(server.isatttach) { c11_dap_send_initialized_event(); server.isatttach = false; + } else if(server.isclientready) { + server.isclientready = false; + return; } } printf("[DEBUGGER INFO] : configure done\n"); @@ -389,15 +399,20 @@ void c11_dap_tracefunc(py_Frame* frame, enum py_TraceEvent event) { } void py_debugger_waitforattach(const char* hostname, unsigned short port) { - c11_dap_init_server(hostname, port); c11_debugger_init(); - c11_dap_configure_debugger(); + c11_dap_init_server(hostname, port); + while(!server.isconfiguredone) { + c11_dap_waitforclient(hostname, port); + c11_dap_configure_debugger(); + if(!server.isconfiguredone) { + c11_socket_close(server.toclient); + printf("[DEBUGGER INFO] : An clinet is ready\n"); + } + } c11_socket_set_block(server.toclient, 0); py_sys_settrace(c11_dap_tracefunc, true); } void py_debugger_exit(int exitCode) { - char body[64]; - snprintf(body, sizeof(body), "{\"exitCode\":%d}", exitCode); - c11_dap_send_event("exited", body); + c11_dap_send_exited_event(exitCode); } \ No newline at end of file