diff --git a/debugger.c b/debugger.c index 0d6a28f6d239ad6bff79689158aa056540a2ef25..ca5ed029fc6c44acc3ef3b0389e9eecfaf51c55d 100644 --- a/debugger.c +++ b/debugger.c @@ -32,22 +32,13 @@ #include "message_server.h" -static int g_connectFlag = 0; -static int g_client = 0; -void DBG_SetConnectFlag(int flag, int client) -{ - g_connectFlag = flag; - g_client = client; -} - -static int DBG_IsConnect() -{ - return g_connectFlag; -} +static __thread bool g_isServerStarted = 0; +static __thread bool g_isBreakPointSet = 0; +static __thread bool g_isAttachMode = 0; -static int DBG_GetClient() +void DBG_SetDebugMode(bool isAttachMode) { - return g_client; + g_isAttachMode = isAttachMode; } static int DBG_ConnectToIde() @@ -102,14 +93,14 @@ static JSValue DBG_ReadMsg(DebuggerInfo *debuggerInfo) DEBUGGER_LOGE("DBG_ReadMsg fail debuggerInfo=NULL"); return JS_UNDEFINED; } - while (QueueIsEmpty()) { + while (QueueIsEmpty(debuggerInfo->client)) { usleep(DBG_WAITING_TIME); } - const char *message = QueueFront(); + const char *message = QueueFront(debuggerInfo->client); DEBUGGER_LOGI("DBG_ReadMsg %s", message); JSValue msg = JS_ParseJSON(debuggerInfo->cx, message, strlen(message), ""); - QueuePop(); + QueuePop(debuggerInfo->client); return msg; } @@ -850,9 +841,9 @@ static void DBG_Entry(JSContext *cx, int client) return; } debuggerInfo->cx = cx; - debuggerInfo->client = client; + // debuggerInfo->client = client; debuggerInfo->breakpoints = JS_NewObject(cx); - debuggerInfo->isConnected = 1; + // debuggerInfo->isConnected = 1; DBG_SendStopMsg(debuggerInfo, "entry"); } @@ -954,21 +945,33 @@ void DBG_CallDebugger(JSContext *cx, const uint8_t *pc) DEBUGGER_LOGE("DBG_CallDebugger fail debuggerInfo=NULL"); return; } - if (debuggerInfo->isConnected == 0) { + + if (!g_isServerStarted) { pthread_t tid; - if (pthread_create(&tid, NULL, &DBG_StartAgent, NULL) != 0) { + if (pthread_create(&tid, NULL, &DBG_StartAgent, (void*)debuggerInfo) != 0) { DEBUGGER_LOGE("pthread_create fail!"); return; } - while (DBG_IsConnect() == 0) { - usleep(DBG_WAITING_TIME); + g_isServerStarted = true; + if (!g_isAttachMode) { + while (debuggerInfo->isConnected != 1) { + usleep(DBG_WAITING_TIME); + } + DBG_Entry(cx, debuggerInfo->client); + // read msg when first time must be breakpoints msg, and set breakpoints to debugger + DBG_ProcessMsg(debuggerInfo, pc, 0); + g_isBreakPointSet = true; } - DBG_Entry(cx, DBG_GetClient()); - // read msg when first time must be breakpoints msg, and set breakpoints to debugger - DBG_ProcessMsg(debuggerInfo, pc, 0); } - if (QueueIsEmpty() == 0) { + if (g_isAttachMode && (debuggerInfo->isConnected == 1 && !g_isBreakPointSet)) { + // ide attached, accept breakpoints msg + DBG_Entry(cx, debuggerInfo->client); + DBG_ProcessMsg(debuggerInfo, pc, 0); + g_isBreakPointSet = true; + } + + if (QueueIsEmpty(debuggerInfo->client) == 0) { DBG_ProcessMsg(debuggerInfo, pc, 1); } @@ -982,7 +985,7 @@ void DBG_CallDebugger(JSContext *cx, const uint8_t *pc) } } // must check breakpotint first, then process step operation - if (JS_HitBreakpoint(cx, pc) && JS_JudgeConditionBreakPoint(cx, pc)) { + if (g_isBreakPointSet && JS_HitBreakpoint(cx, pc) && JS_JudgeConditionBreakPoint(cx, pc)) { LocInfo loc = JS_GetCurrentLocation(cx, pc); DEBUGGER_LOGI("DBG_CallDebugger hit breakpoint at line %d", loc.line); diff --git a/debugger.h b/debugger.h index 193be9801a88f735ca3d872a562b104a1c85aeb8..05550d27a4bf2b5493f7f760fd29bc0b06ce7391 100644 --- a/debugger.h +++ b/debugger.h @@ -84,13 +84,13 @@ typedef struct LocInfo { typedef struct DebuggerInfo { JSContext *cx; - int client; + volatile int client; int stepOperation; uint32_t depth; LocInfo loc; JSValue breakpoints; int buildConnect; - int isConnected; + volatile int isConnected; } DebuggerInfo; typedef struct DebuggerVariableState { @@ -108,7 +108,7 @@ JSValue JS_DebuggerEvaluate(JSContext *ctx, int stackIndex, JSValue expression); void DBG_FreeSources(JSContext *cx, DebuggerInfo *debuggerInfo); void DBG_CallDebugger(JSContext *cx, const uint8_t *pc); uint32_t DBG_GetValueAsUint32Type(JSContext *cx, JSValue obj, const char *property); -void DBG_SetConnectFlag(int flag, int client); +void DBG_SetDebugMode(bool isAttachMode); #ifdef __cplusplus } diff --git a/message_server.cpp b/message_server.cpp index 317c386eb2b3da6e0cc1133484e9fe5a9fc9971a..4f0332aaf20e2563791f4d20d453f9a020f2f810 100644 --- a/message_server.cpp +++ b/message_server.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,7 @@ #include "securec.h" static std::mutex g_mtx; -static std::list g_readMsgQueue; +static std::map> g_readMsgQueues; static constexpr int MSG_LEN = 9; static constexpr int MAX_CONNECT_CLIENT_NUM = 1; @@ -49,25 +50,25 @@ bool DBG_CopyComponentNameFromAce(const char *srcStr, char *destStr, int maxLen) return true; } -const char* QueueFront() +const char* QueueFront(int client) { g_mtx.lock(); - const char* res = g_readMsgQueue.front().c_str(); + const char* res = g_readMsgQueues[client].front().c_str(); g_mtx.unlock(); return res; } -void QueuePop() +void QueuePop(int client) { g_mtx.lock(); - g_readMsgQueue.pop_front(); + g_readMsgQueues[client].pop_front(); g_mtx.unlock(); } -int QueueIsEmpty() +int QueueIsEmpty(int client) { g_mtx.lock(); - int ret = g_readMsgQueue.empty(); + int ret = g_readMsgQueues[client].empty(); g_mtx.unlock(); return ret; } @@ -132,21 +133,30 @@ static void ReadMsg(int client) msgBuf.get()[msgLen] = '\0'; DEBUGGER_LOGI("dbg msg %s", msgBuf.get()); std::string message(msgBuf.get()); - g_readMsgQueue.push_back(message); + g_readMsgQueues[client].push_back(message); g_mtx.unlock(); return; } + static std::string g_componentName; +static int g_instanceId; -void DBG_SetComponentName(const char *name, int size) +void DBG_SetComponentNameAndInstanceId(const char *name, int size, int instanceId) { if (size <= 0) { DEBUGGER_LOGE("DBG_SetComponentName fail"); return; } g_componentName = name; + g_instanceId = instanceId; +} + +void DBG_SetNeedDebugBreakPoint(bool needDebugBreakPoint) +{ + DEBUGGER_LOGI("NeedDebugBreakPoint: %d", needDebugBreakPoint); + DBG_SetDebugMode(!needDebugBreakPoint); } static std::string DBG_GetComponentName() @@ -164,10 +174,10 @@ static int DBG_StartServer() if (fd < 0) { return FAIL_CAUSE_SOCKET_COMMON_FAIL; } - int appPid = getpid(); - std::string pidStr = std::to_string(appPid); + + std::string instanceIdStr = std::to_string(g_instanceId); std::string component = DBG_GetComponentName(); - std::string sockName = pidStr + component; + std::string sockName = instanceIdStr + component; struct sockaddr_un un; if (memset_s(&un, sizeof(un), 0, sizeof(un)) != EOK) { DEBUGGER_LOGE("DBG_StartServer memset_s fail"); @@ -201,12 +211,21 @@ static int DBG_StartServer() void *DBG_StartAgent(void *args) { int client = DBG_StartServer(); - DEBUGGER_LOGI("DBG_StartAgent client = %d", client); if (client < 0) { DEBUGGER_LOGE("DBG_StartAgent fail"); return nullptr; } - DBG_SetConnectFlag(1, client); + + auto debugger_info = (DebuggerInfo*)args; + g_mtx.lock(); + debugger_info->client = client; + debugger_info->isConnected = 1; + g_mtx.unlock(); + + std::list messageList; + g_readMsgQueues[client] = messageList; + DEBUGGER_LOGI("DBG_StartAgent client = %d", client); + while (true) { ReadMsg(client); } diff --git a/message_server.h b/message_server.h index 225b6e04e69aef169abfb6e3fc51bcdae08bb656..6ef7e52545e6a6f48fa39ac6fb83ac0e4ac38161 100644 --- a/message_server.h +++ b/message_server.h @@ -27,12 +27,13 @@ extern "C" { #endif /* End of #ifdef __cplusplus */ -const char* QueueFront(); -void QueuePop(); -int QueueIsEmpty(); +const char* QueueFront(int client); +void QueuePop(int client); +int QueueIsEmpty(int client); void *DBG_StartAgent(void *args); bool DBG_CopyComponentNameFromAce(const char *srcStr, char *destStr, int maxLen); -void DBG_SetComponentName(const char *name, int size); +void DBG_SetComponentNameAndInstanceId(const char *name, int size, int instanceId); +void DBG_SetNeedDebugBreakPoint(bool needDebugBreakPoint); #ifdef __cplusplus } diff --git a/quickjs.c b/quickjs.c index 40024dca9d568769563ebb0d587bb2b1c2b2bf8d..eca45d445e770fa3c1f9389907aecbb0ab4e6074 100644 --- a/quickjs.c +++ b/quickjs.c @@ -426,7 +426,7 @@ struct JSContext { JSShape *array_shape; /* initial shape for Array objects */ #ifdef ENABLE_JS_DEBUG - DebuggerInfo debugger_info; + DebuggerInfo *debugger_info; #endif JSValue *class_proto; @@ -2146,8 +2146,17 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->header.ref_count = 1; add_gc_object(rt, &ctx->header, JS_GC_OBJ_TYPE_JS_CONTEXT); +#ifdef ENABLE_JS_DEBUG + ctx->debugger_info = js_malloc_rt(rt, sizeof(DebuggerInfo)); + if (!ctx->debugger_info) { + DEBUGGER_LOGE("Create debugger_info failed!"); + return NULL; + } +#endif + ctx->class_proto = js_malloc_rt(rt, sizeof(ctx->class_proto[0]) * rt->class_count); + if (!ctx->class_proto) { js_free_rt(rt, ctx); return NULL; @@ -16204,7 +16213,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, }; #define SWITCH(pc) goto *active_dispatch_table[opcode = *pc++]; #define CASE(op) case_debugger_ ## op: DBG_CallDebugger(caller_ctx, pc); case_ ## op - const void * const * active_dispatch_table = caller_ctx->debugger_info.isConnected + const void * const * active_dispatch_table = caller_ctx->debugger_info->isConnected ? debugger_dispatch_table : dispatch_table; #else #define SWITCH(pc) goto *dispatch_table[opcode = *pc++]; @@ -54209,7 +54218,7 @@ DebuggerInfo *JS_GetDebuggerInfo(JSContext *cx) if (cx == NULL) { return NULL; } - return &cx->debugger_info; + return cx->debugger_info; } static int JS_FunctionDefineInit(JSContext *ctx, JSFunctionDef *fd, JSFunctionBytecode *byte_code)