#include "stdafx.h" #include "version.h" #include "SpBase.h" #include #include "SpTimer.h" #include "SpEntity.h" #include "SpModule.h" #include "RVCEventCode.h" #ifdef WIN32 #include "SpBaseRoutine.h" #endif #include "SpMisc.h" #include "SpClientSessionFunction.h" #include "sockutil.h" #include "fileutil.h" #include "memutil.h" #include "dbgutil.h" #include "sp_shm.h" #include "sp_dbg_export.h" #include "sp_def.h" #include "sp_env.h" #include "DumpException.h" #ifdef RVC_OS_WIN #include "sp_checkEntity.h" #pragma comment(lib, "dbghelp.lib") #include #else #include #include #endif // RVC_OS_WIN #include "SpSecureClient.h" #include "IHttpFunc.h" #include #include #include #ifndef RVC_OS_WIN static SpModule* g_module = NULL; #endif //NOT RVC_OS_WIN SpModule *GetSpModule() { #ifdef RVC_OS_WIN SpModule *curModule = NULL; if (findThreadModule(GetCurrentThreadId(), (void **)&curModule)) return curModule; else { CSimpleStringA mod_name = TraceStack(); if (CSimpleStringA("") == mod_name) { return NULL; } SetthreadGroup(GetCurrentThreadId(), mod_name); if (findThreadModule(GetCurrentThreadId(), (void**)&curModule)) return curModule; } return NULL; #else return g_module; #endif //RVC_OS_WIN } #ifdef RVC_OS_WIN static LONG WINAPI SuppressError(struct _EXCEPTION_POINTERS* ExceptionInfo) { //get active ver char szIniPath[MAX_PATH] = { 0 }; sp_version_t active_version = { 0 }; auto rc = sp_dir_get_path(sp_get_env()->dir, SP_DIR_INSTALL_INI, NULL, szIniPath, MAX_PATH); TOOLKIT_ASSERT(rc == 0); sscanf(strrchr(sp_get_env()->dir->base_path, '\\') + 1, "%d.%d.%d.%d", &active_version.major, &active_version.minor, &active_version.revision, &active_version.build); std::string dmpFileStr; char tmp[MAX_PATH], tmpPath[MAX_PATH]; GetModuleFileNameA(NULL, tmpPath, MAX_PATH); *strrchr(tmpPath, SPLIT_SLASH) = 0; *strrchr(tmpPath, SPLIT_SLASH) = 0; *strrchr(tmpPath, SPLIT_SLASH) = 0; *strrchr(tmpPath, SPLIT_SLASH) = 0; *strrchr(tmpPath, SPLIT_SLASH) = 0; wsprintfA(tmp, "%s\\rvc\\dmp\\expt.%d_%d_%d_%d.%s.%d.%d.log", tmpPath, active_version.major, active_version.minor , active_version.revision, active_version.build, GetSpModule() ? GetSpModule()->get_mod()->cfg->name : "", GetCurrentThreadId(), GetCurrentProcessId()); HANDLE hLogFile = ::CreateFileA(tmp, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hLogFile != INVALID_HANDLE_VALUE) { DumpExceptionInfo(ExceptionInfo, hLogFile); FlushFileBuffers(hLogFile); SetEndOfFile(hLogFile); CloseHandle(hLogFile); } wsprintfA(tmp, "%s\\rvc\\dmp\\expt.%d_%d_%d_%d.%s.%d.%d.dmp", tmpPath, active_version.major, active_version.minor , active_version.revision, active_version.build, GetSpModule() ? GetSpModule()->get_mod()->cfg->name : "", GetCurrentThreadId(), GetCurrentProcessId()); HANDLE hDumpFile = CreateFileA( tmp, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( ( hDumpFile != NULL ) && ( hDumpFile != INVALID_HANDLE_VALUE ) ) { MINIDUMP_EXCEPTION_INFORMATION mdei; mdei.ThreadId = GetCurrentThreadId(); mdei.ExceptionPointers = ExceptionInfo; mdei.ClientPointers = FALSE; MINIDUMP_TYPE mdt = MiniDumpWithIndirectlyReferencedMemory; BOOL rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, mdt, (ExceptionInfo != 0) ? &mdei : 0, 0, 0 ); CloseHandle( hDumpFile ); } DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setLogCode(ERR_ENTITY_EXCEPTION).setVtmCode(RTAERR_ENTITY_EXCEPTION)("exit entity exception, saveDmp, %s, detail:%d:%s" , tmp, dmpFileStr.length(), dmpFileStr.c_str()); Sleep(1500);//wait until all log send ExitProcess(Error_Exception); // exit process to suppress reporting exception return EXCEPTION_EXECUTE_HANDLER; } #else #include static void HandleSignalCallback(int signalNo) { switch (signalNo) { case SIGSEGV: { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("=========>>> capture signal SIGSEGV <<<========="); void* l_buffer[512]; char** l_ptrace; //char l_s8aBuff[128] = { 0x00 }; //snprintf(l_s8aBuff, sizeof(l_s8aBuff), "cat /proc/%d/maps", getpid()); //system(l_s8aBuff); //objdump -d libbacktrace.so > log.txt DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("Dump stack start..."); int size = backtrace(l_buffer, 512); l_ptrace = backtrace_symbols(l_buffer, size); if (NULL == l_ptrace) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("backtrace_symbols"); exit(1); } for (int i = 0; i < size; i++) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)(" [%02d] %s", i, l_ptrace[i]); } DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("Dump stack end..."); free(l_ptrace); exit(-1); break; } case SIGKILL: DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("=========>>> capture signal SIGKILL <<<========="); break; case SIGTERM: DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("=========>>> capture signal SIGTERM <<<========="); break; default: DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("=========>>> capture signal %d <<<=========", signalNo); break; } return; } static LONG WINAPI SuppressError(struct _EXCEPTION_POINTERS* ExceptionInfo) { LONG result(0); #if 1 struct sigaction siga; siga.sa_handler = HandleSignalCallback; siga.sa_flags = 0; sigemptyset(&siga.sa_mask); if (0 > sigaction(SIGSEGV, &siga, NULL)) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("register signal 'SIGSEGV' failed! %s %d", strerror(errno), errno); result = -1; } //if (0 > sigaction(SIGTERM, &siga, NULL)) { // sp_dbg_error("register signal 'SIGTERM' failed! %s %d", strerror(errno), errno); result = -1; //} //if (0 > sigaction(SIGKILL, &siga, NULL)) { // sp_dbg_error("register signal 'SIGKILL' failed! %d", errno); result = -1; //} #endif return result; } #endif //RVC_OS_WIN SPBASE_API void GetLibVersion(CVersion& version) { CVersion ver(VER_Major, VER_Minor, VER_Revision, VER_Build); version = ver; } SPBASE_API LPCSTR GetLibBuildDate() { #if defined(WITH_DEBUG) static char buildDate[] = __DATE__ " " __TIME__ " Debug"; #elif defined(WITH_NO_DEBUG) static char buildDate[] = __DATE__ " " __TIME__ " Release"; #else static char buildDate[] = __DATE__ " " __TIME__; #endif // WITH_DEBUG return buildDate; } SPBASE_API void LogEvent(const SeverityLevelEnum eLevel,DWORD dwUserEventCode,const char *pszMessage) {//MAX string len < 1024 SpModule *pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Event, eLevel, 0, dwUserEventCode, pszMessage); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserEventCode).GetData()) ("Event: {%s}(uc=0x%X)", pszMessage, dwUserEventCode); } SPBASE_API void LogError(const SeverityLevelEnum eLevel, ErrorCodeEnum dwSysErrorCode,DWORD dwUserErrorCode,const char *pszMessage) { SpModule *pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Error, eLevel, dwSysErrorCode, dwUserErrorCode, pszMessage); } else { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("LogError failed!can not find the module"); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Error: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); } SPBASE_API void LogFatal(const SeverityLevelEnum eLevel, ErrorCodeEnum dwSysErrorCode, DWORD dwUserErrorCode, const char* pszMessage) { SpModule* pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Fatal, eLevel, dwSysErrorCode, dwUserErrorCode, pszMessage); } else sp_dbg_info("LogFatal failed!can not find the module"); DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Fatal: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); } SPBASE_API void LogNotify(const NotifyLevelEnum eLevel, ErrorCodeEnum dwSysErrorCode, DWORD dwUserErrorCode, const char* pszMessage) { SpModule* pModule = GetSpModule(); if (pModule) { const SeverityLevelEnum severityLevel = (SeverityLevelEnum)(int)eLevel; pModule->LogMessage(Log_Notify, severityLevel, dwSysErrorCode, dwUserErrorCode, pszMessage); } else { sp_dbg_info("LogNotify failed!can not find the module"); } switch (eLevel) { case Notify_Info: DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Notify: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); break; case Notify_Warn: DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Notify: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); break; case Notify_Error: DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Notify: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); break; default: DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Notify: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); break; } } SPBASE_API void LogWarn(const SeverityLevelEnum eLevel, ErrorCodeEnum dwSysErrorCode,DWORD dwUserErrorCode, const char *pszMessage) { SpModule *pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Warning, eLevel, dwSysErrorCode, dwUserErrorCode, pszMessage); } // write a copy in dbg log DbgWithLink(eLevel == Severity_Low ? LOG_LEVEL_INFO : LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Warn: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); } SPBASE_API void LogAssert(const char *pszMessage,const char *pszFile,const int nLine) { SpModule *pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Debug, Severity_Middle, 0, 0, CSimpleStringA::Format("assert fail: {%s}, file: {%s}, line: {%d}, stack: {%s}", pszMessage, _GetFileName(pszFile), nLine, #ifdef RVC_OS_WIN (const char*)DumpStack(2) #else "not implement, TODO:" #endif //RVC_OS_WIN )); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(ERR_ENTITY_ASSERT).GetData())("Assert fail: {%s}, file: {%s}, line: {%d}, stack: {%s}", pszMessage, _GetFileName(pszFile), nLine, #ifdef RVC_OS_WIN (const char*)DumpStack(2) #else "not implement, TODO:" #endif //RVC_OS_WIN ); } SPBASE_API void LogTrace(const char *pszMessage,const char *pszFile,const int nLine) { SpModule *pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Debug, Severity_None, 0, 0, pszMessage); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Trace: {%s}, file: {%s}, line: {%d}", pszMessage, _GetFileName(pszFile), nLine); } SPBASE_API void LogEvent(const SeverityLevelEnum eLevel, DWORD dwUserEventCode, const char* pszMessage, const linkContext& t_context) { SpModule* pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Event, eLevel, 0, dwUserEventCode, pszMessage, t_context); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwUserEventCode).GetData()) ("Event: {%s}(uc=0x%X)", pszMessage, dwUserEventCode); } SPBASE_API void LogError(const SeverityLevelEnum eLevel, ErrorCodeEnum dwSysErrorCode, DWORD dwUserErrorCode, const char* pszMessage, const linkContext& t_context) { SpModule* pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Error, eLevel, dwSysErrorCode, dwUserErrorCode, pszMessage, t_context); } else { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("LogError failed!can not find the module"); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(dwSysErrorCode).GetData()) ("Error: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); } SPBASE_API void LogWarn(const SeverityLevelEnum eLevel, ErrorCodeEnum dwSysErrorCode, DWORD dwUserErrorCode, const char* pszMessage, const linkContext& t_context) { SpModule* pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Warning, eLevel, dwSysErrorCode, dwUserErrorCode, pszMessage, t_context); } // write a copy in dbg log DbgWithLink(eLevel == Severity_Low ? LOG_LEVEL_INFO : LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setVtmCode(DWORD2Hex(dwUserErrorCode).GetData()) ("Warn: {%s}(sc=0x%X, uc=0x%X)", pszMessage, dwSysErrorCode, dwUserErrorCode); } SPBASE_API void LogAssert(const char* pszMessage, const char* pszFile, const int nLine, const linkContext& t_context) { SpModule* pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Debug, Severity_Middle, 0, 0, CSimpleStringA::Format("assert fail: {%s}, file: {%s}, line: {%d}, stack: {%s}", pszMessage, _GetFileName(pszFile), nLine, #ifdef _WIN32 (const char*)DumpStack(2) #else "not implement, TODO:" #endif //_WIN32 ), t_context); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setVtmCode(DWORD2Hex(ERR_ENTITY_ASSERT).GetData())("Assert fail: {%s}, file: {%s}, line: {%d}, stack: {%s}", pszMessage, _GetFileName(pszFile), nLine, #ifdef _WIN32 (const char*)DumpStack(2) #else "not implement, TODO:" #endif //_WIN32 ); } SPBASE_API void LogTrace(const char* pszMessage, const char* pszFile, const int nLine, const linkContext& t_context) { SpModule* pModule = GetSpModule(); if (pModule) { pModule->LogMessage(Log_Debug, Severity_None, 0, 0, pszMessage, t_context); } // write a copy in dbg log DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Trace: {%s}, file: {%s}, line: {%d}", pszMessage, _GetFileName(pszFile), nLine); } #include "log.h" #ifdef RVC_OS_LINUX SPBASE_API void SpGetToken(char* channelId, char* token) { sp_env_t* env = sp_get_env(); if (NULL != env && NULL != env->cfg && NULL != env->cfg->shell_ini && env->cfg->shell_ini->channelId != NULL && env->cfg->shell_ini->token != NULL) { snprintf(channelId, MAX_TOKEN_LEN, "%s", env->cfg->shell_ini->channelId); snprintf(token, MAX_TOKEN_LEN, "%s", env->cfg->shell_ini->token); } else if (NULL == env) DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SpGetToken can not get token!env == NULL"); else if (NULL == env->cfg) DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SpGetToken can not get token!env->cfg == NULL"); else if (NULL == env->cfg->shell_ini) DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SpGetToken can not get token!env->cfg->shell_ini == NULL"); else if (NULL == env->cfg->shell_ini->channelId) DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SpGetToken can not get token!env->cfg->shell_ini->channelId == NULL"); else if (NULL == env->cfg->shell_ini->token) DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SpGetToken can not get token!env->cfg->shell_ini->token == NULL"); } #endif extern "C" SPBASE_API void Dbg(const char *str, ...) { if (str == nullptr) return; va_list arg; va_start(arg, str); vDbg(str, arg); va_end(arg); } extern "C" SPBASE_API void vDbg(const char *str, va_list list) { int n = _vscprintf(str, list); if (n > 1024) n = 1024; char *buf = (char*)_alloca(n + 1); memset(buf, '\0', n + 1); /*write at most n bytes(including the terminating null byte '\0') to buf*/ vsnprintf(buf, n + 1, str, list); // plus 1 to n, never changed code but the log lost one char [4/1/2020 16:25 Gifur] buf[n] = '\0'; #if defined(_MSC_VER) sp_dbg_debugNoOut("Debug: {%s}", buf); //打印到文件 #else sp_dbg_debug("Debug: {%s}", buf); #endif //_MSC_VER #ifdef RVC_OS_WIN SpModule* pModule = GetSpModule(); if (pModule) { SpEntity* pEntity = (SpEntity*)(getEntityResource()->m_Entity); if (pEntity != NULL) { auto pEntCfg = pEntity->get_cfg_ent(); if (pEntCfg != NULL) pEntity->LogMessage(Log_Debug, Severity_None, 0, 0, buf); } } #endif // RVC_OS_WIN } static bool RegistMain(HMODULE hModule,EntryRoutine Main, EntryRoutine Exit) { SpModule::SetEntryRoutine(Main, Exit); return true; } static HMODULE LoadModuleLibrary(sp_mod_t *mod) { sp_env_t *env = sp_get_env(); char tmp[MAX_PATH]; sp_dir_get_path(env->dir, SP_DIR_MODULE_BIN, mod->cfg->name, tmp, sizeof(tmp)); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("load module library: %s", tmp); return LoadLibraryA(tmp); } /*It seems never been used anywhere.*/ SPBASE_API HINSTANCE SpLoadLibrary(const char *file) { sp_env_t *env = sp_get_env(); if (env) { char tmp[MAX_PATH]; sprintf(tmp, "%s" SPLIT_SLASH_STR "%s", env->dir->dep_path, file); return LoadLibraryA(tmp); } else { return NULL; } } /*only sphost would invoke it.*/ extern "C" SPBASE_API int __stdcall SpExit(const char* mod_name) { #ifdef RVC_OS_WIN DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Do SpExit!"); SetthreadGroup(GetCurrentThreadId(), mod_name); CleanModuleThread(mod_name); sp_iom_stop(GetSpModule()->get_iom()); GetSpModule()->Term(); sp_shm_term(); sp_dbg_term(); sp_iom_destroy(GetSpModule()->get_iom()); delete GetSpModule(); //winsock_term(); FreeLibrary(getEntityResource()->m_Module); DestoryModuleInfo(mod_name); #else if (sp_shm_is_newalloc()) return 0; /*spshell*/ if (g_module) { delete g_module; g_module = nullptr; } #endif //RVC_OS_WIN return 0; } extern "C" SPBASE_API int __stdcall SpRun(const char *mod_name, int epid, int range, int group, int saveFile) { ErrorCodeEnum Error = Error_Unexpect; if (!mod_name) { return Error_Param; } if (epid == SP_INVALID_MOD_ID) { return Error_Param; } #ifdef RVC_OS_WIN if (findModuleByName(mod_name)) //检测实体是否已创建 SpExit(mod_name); bool result = group == 0 ? CreateModuleInfo(ENTITY_SINGLE_GROUPNAME) : CreateModuleInfo(mod_name); //the SetthreadGroup routine would never return false, so the group variable must be not-zero if (!result || !SetthreadGroup(GetCurrentThreadId(), mod_name)) return Error_Duplication; #else if (g_module) { return Error_Duplication; } #endif //RVC_OS_WIN void* hint_addr = NULL; HMODULE hModule = NULL; sp_env_t* env = NULL; sp_mod_t* mod = NULL; sp_cfg_shell_module_t* cfg_mod = NULL; SpModule* curModule = NULL; if (winsock_init() != 0) { sp_dbg_error("winsock init failed!"); Error = Error_NetBroken; goto on_error; } SetTokenCallBack(getHttpToken); #ifdef RVC_OS_LINUX SetRestfulTokenCallBack(getHttpToken); #endif //need init shm first, because log_record save in shm hint_addr = sp_shm_init(range, FALSE); create_log_producer_default(mod_name, epid); if (saveFile) sp_dbg_init(mod_name, 1); else sp_dbg_init(mod_name, 0); EntityResource::setSaveFile(saveFile); sp_dbg_set_level(XLOG_LEVEL_DEBUG); if (!hint_addr) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shm init failed!"); Error = Error_Null; goto on_error; } sp_trace_init(); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("==============SpRun(%s) start==============", mod_name); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("process id: %d, curLogLevel:%d", GetCurrentProcessId(), getCurLogLevel()); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shm init ok! hint_addr: %p", hint_addr); env = sp_get_env(); if (!env) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("module env object init failed(env is null)!"); Error = Error_Unexpect; goto on_error; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("retrieve env object ok!"); mod = sp_mod_mgr_find_module_by_idx(env->mod_mgr, epid); if (!mod) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("find shm module object failed!"); Error = Error_NotExist; goto on_error; } //sp_dbg_info("find module %s id %d ok!", mod->cfg->name, mod->cfg->idx); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("module %s id %d static file version: %d.%d.%d.%d", mod->cfg->name, mod->cfg->idx, mod->cfg->version.major, mod->cfg->version.minor, mod->cfg->version.revision, mod->cfg->version.build); SpInitUUID((WORD)mod->cfg->idx); cfg_mod = sp_cfg_get_module_by_idx(env->cfg, epid); if (!cfg_mod) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("get module %s cfg object failed!", mod->cfg->name); Error = Error_NotExist; goto on_error; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("find cfg module object %s id %d ok!", cfg_mod->name, cfg_mod->idx); #ifdef RVC_OS_WIN SetUnhandledExceptionFilter(&SuppressError); #else SuppressError(NULL); #endif //RVC_OS_WIN #ifdef RVC_OS_WIN curModule = new SpModule(mod, cfg_mod); getEntityResource()->m_Module = LoadModuleLibrary(mod); if (!getEntityResource()->m_Module) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("load module library %s failed! GetLastError = %d", mod->cfg->name, GetLastError()); Error = Error_Unregisted; goto on_error; } curModule->getEntryRoutine(&(getEntityResource()->m_pfMain), &(getEntityResource()->m_pfExit)); Error = curModule->Init(env->url); if (Error) { delete curModule; curModule = NULL; goto on_error; } #else g_module = new SpModule(mod, cfg_mod); hModule = LoadModuleLibrary(mod); if (!hModule) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("load module library %s failed! %s", mod->cfg->name, DLoadErrorString()); Error = Error_Unregisted; goto on_error; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to init module..."); Error = g_module->Init(env->url); if (Error) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("init moudle returned %s", SpStrError(Error)); goto on_error; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("init moudle succ."); #endif //RVC_OS_WIN SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); #ifdef RVC_OS_WIN if (!SetSpModule(mod_name, curModule)) { Error = Error_Unexpect; goto on_error; } sp_trace_term(); Error = curModule->Run(); curModule->Term(); FreeLibrary(getEntityResource()->m_Module); delete curModule; curModule = NULL; #else sp_trace_term(); Error = g_module->Run(); g_module->Term(); #endif //RVC_OS_WIN on_error: #ifndef RVC_OS_WIN if (hModule) { FreeLibrary(hModule); hModule = NULL; } if (g_module) { delete g_module; g_module = nullptr; } #endif //NOT RVC_OS_WIN if (!!sp_trace_exist()) { char* last_err = NULL; sp_trace_retrieve(&last_err, NULL); if (last_err) { sp_mod_supress_last_err_for_all_entity(mod, last_err); FREE(last_err); } } sp_shm_term(); //destroy_log_producer_default(); return Error; } extern "C" SPBASE_API const char* SpStrError(ErrorCodeEnum errorCode) { return sp_strerror((int)errorCode); } SPBASE_API CSimpleStringA GetSysErrMsg(int nErrCode) { char szBuf[2048] = {}; DWORD dwRet = FormatMessageA( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, nErrCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szBuf, sizeof(szBuf)-1, NULL); char *p = strrchr(szBuf, '\r'); if (p != NULL) *p = ' '; p = strrchr(szBuf, '\n'); if (p != NULL) *p = ' '; return dwRet > 0 ? szBuf : CSimpleStringA::Format("get error message fail: %d", GetLastError()); } SPBASE_API const char *_GetFileName(const char *pszFilePath) { int i=strlen(pszFilePath); for( ; i>0 && pszFilePath[i-1]!=SPLIT_SLASH; i--)NULL; return pszFilePath+i; } #ifdef RVC_OS_WIN extern "C" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { DisableThreadLibraryCalls(hModule); break; } case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; } #endif //RVC_OS_WIN ModuleBase::~ModuleBase() { #ifdef RVC_OS_WIN getEntityResource()->m_moduleBase = NULL; #else ModuleBase::s_pModuleInst = NULL; #endif //RVC_OS_WIN for (int i = 0; i < m_nEntityCount; ++i) { if (m_pEntityArray[i]) { #ifdef RVC_OS_WIN //属于实体关闭掉,会自动清理,实际上不做对应的delete也行 //基于该部分出了的问题,应该用share_ptr来处理 //不过因为需要导出到spbase.h中,处理比较麻烦 //__try { // delete m_pEntityArray[i]; //} //__finally { // m_pEntityArray[i] = NULL; //} #else delete m_pEntityArray[i]; m_pEntityArray[i] = NULL; #endif //RVC_OS_WIN } } m_nEntityCount = 0; } static ErrorCodeEnum __Init() { #ifdef RVC_OS_WIN ModuleBase* pThis = (ModuleBase*)(getEntityResource()->m_moduleBase); #else ModuleBase* pThis = ModuleBase::s_pModuleInst; #endif //RVC_OS_WIN _ASSERT(pThis); return pThis->Init(); } static ErrorCodeEnum __Exit() { #ifdef RVC_OS_WIN ModuleBase* pThis = (ModuleBase*)(getEntityResource()->m_moduleBase); #else ModuleBase* pThis = ModuleBase::s_pModuleInst; #endif //RVC_OS_WIN _ASSERT(pThis); return pThis->Exit(); } ErrorCodeEnum ModuleBase::Init() { ErrorCodeEnum Error = Error_Succeed; for (int i = 0; i < m_nEntityCount; ++i) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to regist entity %s", m_pEntityArray[i]->GetEntityName()); Error = RegistEntity(m_pEntityArray[i]); if (Error) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("regist entity %s returned %s", m_pEntityArray[i]->GetEntityName(), SpStrError(Error)); break; } } return Error; } ErrorCodeEnum ModuleBase::Exit() { ErrorCodeEnum Error = Error_Succeed; for (int i = 0; i < m_nEntityCount; ++i) { Error = UnregistEntity(m_pEntityArray[i]); if (Error) break; } return Error; } BOOL ModuleBase::DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { bool ret = RegistMain(hInstance, &__Init, &__Exit); if (!ret) return FALSE; DisableThreadLibraryCalls(hInstance); m_hInstance = hInstance; } return TRUE; } ErrorCodeEnum ModuleBase::RegistEntity(CEntityBase *pEntity) { SpModule *pModule = GetSpModule(); SpSecureClient::SetSecureEntity(pEntity); if (!pModule) return Error_Null; return pModule->AddEntityBase(pEntity); } ErrorCodeEnum ModuleBase::UnregistEntity(CEntityBase *pEntity) { SpModule *pModule = GetSpModule(); return pModule->RemoveEntityBase(pEntity); } ErrorCodeEnum ModuleBase::GetRegistEntity(const char *pszEntityName,CSmartPointer &pEntity) { SpModule *pModule = GetSpModule(); return pModule->GetEntityBase(pszEntityName, pEntity); } #ifndef RVC_OS_WIN ModuleBase* ModuleBase::s_pModuleInst = NULL; #endif //NOT RVC_OS_WIN ModuleBase* ModuleBase::GetModuleBase() { #ifdef RVC_OS_WIN return (ModuleBase*)(getEntityResource()->m_moduleBase); #else return ModuleBase::s_pModuleInst; #endif //RVC_OS_WIN } ModuleBase::ModuleBase() :m_hInstance(NULL), m_nEntityCount(0) { #ifdef RVC_OS_WIN getEntityResource()->m_moduleBase = this; #else ModuleBase::s_pModuleInst = this; #endif //RVC_OS_WIN } CClientSessionBase::~CClientSessionBase() { if (m_pSessionFunction) { SpClientSessionFunction *pFunction = dynamic_cast(m_pSessionFunction); m_pSessionFunction = NULL; pFunction->DecrementRef(); } }