sphost.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include "precompile.h"
  2. #include "memtrace.h"
  3. #include "sp_shm.h"
  4. #include "sp_def.h"
  5. #include "fileutil.h"
  6. #include <time.h>
  7. #include <locale.h>
  8. #include <winpr/library.h>
  9. #include <winpr/environment.h>
  10. #include <winpr/registry.h>
  11. #include <winpr/sysinfo.h>
  12. #ifdef _WIN32
  13. #include "modManage.h"
  14. #include "sphostMonitor.h"
  15. #else
  16. #include <winpr/wlog.h>
  17. #include "SpHostLog.h"
  18. #define TAG "sphost"
  19. #endif //_WIN32
  20. #define ARG_NUM 4
  21. HANDLE threadRunLock;
  22. #define BUFSIZE 512
  23. #define DEFAULT_MEMORY_CLEAN_TIME 1800
  24. #define DEFAULT_WAITENTITY_END 5000
  25. #ifdef _WIN32
  26. #define PROCESS_SPSHELL "spshell.exe"
  27. #else
  28. #define PROCESS_SPSHELL "spshell"
  29. #endif //_WIN32
  30. // sphost.exe <mod_name> <epid> <hint_addr>
  31. int SPBASE_API __stdcall SpRun(const char* mod_name, int epid, int range, int group, int saveFile);
  32. int SPBASE_API __stdcall SpExit(const char* mod_name);
  33. void SPBASE_API __stdcall setCurEntityIdx(int idx);
  34. int g_entityStart = 0;
  35. int g_saveFile = 0;
  36. static void SetEnvPath(const char *mod_name)
  37. {
  38. char path[MAX_PATH];
  39. char *pe;
  40. DWORD dwSize;
  41. char *buf;
  42. const char *var = "PATH";
  43. dwSize = GetEnvironmentVariableA(var, NULL, 0);
  44. buf = (char*)malloc(dwSize+MAX_PATH*3);
  45. if (buf == NULL)
  46. return;
  47. dwSize = GetEnvironmentVariableA(var, buf, dwSize);
  48. dwSize = GetCurrentDirectoryA(MAX_PATH, path);
  49. pe = &path[0] + dwSize;
  50. // append dmp subdir to %PATH%
  51. strcpy(pe, SPLIT_SLASH_STR "dmp");
  52. if (ExistsDirA(path)) {
  53. strcat(buf, ENV_SEP_STR);
  54. strcat(buf, path);
  55. SetEnvironmentVariableA(var, buf);
  56. }
  57. // append dep\mod_xxx subdir to %PATH%
  58. strcpy(pe, SPLIT_SLASH_STR "dep" SPLIT_SLASH_STR);
  59. strcat(pe, mod_name);
  60. if (ExistsDirA(path)) {
  61. strcat(buf, ENV_SEP_STR);
  62. strcat(buf, path);
  63. SetEnvironmentVariableA(var, buf);
  64. }
  65. // append dev\mod_xxx subdir to %PATH%
  66. strcpy(pe, SPLIT_SLASH_STR "dev" SPLIT_SLASH_STR);
  67. strcat(pe, mod_name);
  68. if (ExistsDirA(path)) {
  69. strcat(buf, ENV_SEP_STR);
  70. strcat(buf, path);
  71. SetEnvironmentVariableA(var, buf);
  72. }
  73. free(buf);
  74. SetEnvironmentVariableA("ModuleName", mod_name);
  75. }
  76. #ifdef RVC_OS_WIN
  77. DWORD sphostMonitor(LPVOID param)
  78. {
  79. DWORD shellId = (DWORD )param;
  80. HANDLE spShellProcess = NULL;
  81. int waitTimes = 1;
  82. if (0 == shellId || NULL == (spShellProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, shellId)))
  83. {
  84. Sleep(1000 * 30); //do not affact entity start
  85. DbgWithLink_sphost("can not find shell id %d", shellId);
  86. if (NULL == (spShellProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIdFromName(PROCESS_SPSHELL))))//获取的是准确的spshell.exe的pid
  87. {
  88. CloseHandle(spShellProcess);
  89. ExitProcess(-1); //can not find spShell
  90. }
  91. }
  92. while (WAIT_TIMEOUT == WaitForSingleObject(spShellProcess, 5000)) //spshell exit
  93. {
  94. //置换内存到虚拟内存
  95. Sleep(1000);
  96. }
  97. ExitProcess(0);
  98. return 0;
  99. }
  100. DWORD checkEntityStart(LPVOID param)
  101. {//仅检测是否被调用了start命令
  102. Sleep(1000 * 60);
  103. if(!g_entityStart)
  104. ExitProcess(-1);
  105. return 0;
  106. }
  107. DWORD modRun(LPVOID param)
  108. {
  109. mod_runInfo *curModInfo = (mod_runInfo*)param;
  110. __try{
  111. SetEnvPath(curModInfo->mod_name); //Add env path, \dmp, \dev\mod_name, \dep\mod_name
  112. DbgWithLink_sphost("%s entity modRun, SpRun", curModInfo->mod_name);
  113. SpRun(curModInfo->mod_name, curModInfo->epid , curModInfo->range, curModInfo->group, g_saveFile);
  114. }
  115. __finally
  116. {
  117. DbgWithLink_sphost("Entity %s exit!", curModInfo->mod_name);
  118. }
  119. return 0;
  120. }
  121. /*It seems no use anywhere*/
  122. //DWORD modExit(LPVOID param)
  123. //{
  124. // mod_exitInfo *curModInfo = (mod_exitInfo*)param;
  125. // SpExit(curModInfo->mod_name);
  126. // return 0;
  127. //}
  128. DWORD runThreadAndMonitor(LPVOID param)
  129. {
  130. mod_runInfo *curModInfo = (mod_runInfo*) param;
  131. DWORD exitCode = -1;
  132. HANDLE curMutex;
  133. char mod_name[MAX_PATH] = "";
  134. sprintf_s(mod_name, sizeof(mod_name), "%s", curModInfo->mod_name);//防止map的迭代器失效
  135. curMutex = CreateMutex(NULL, TRUE, curModInfo->modMutexName);
  136. if (NULL == curMutex)
  137. return -1;
  138. if (NULL != queryModInfo(mod_name))
  139. removeModInfo(mod_name);
  140. curModInfo->threadHandle = GetCurrentThread();
  141. AddmodInfo(curModInfo, curModInfo->mod_name);
  142. SetEvent(threadRunLock); //此时,主线程中param析构,会导致curModInfo失效
  143. modRun(curModInfo);
  144. // Run mod Run by thread
  145. /*
  146. curThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&modRun, curModInfo, 0, &curModInfo->threadId);
  147. if (NULL != curThread)
  148. {
  149. const mod_runInfo *queryInfo = queryModInfo(mod_name);
  150. if (NULL != queryInfo)
  151. removeModInfo(mod_name);
  152. curModInfo->threadHandle = curThread;
  153. AddmodInfo(curModInfo, curModInfo->mod_name);
  154. SetEvent(threadRunLock); //此时,主线程中param析构,会导致curModInfo失效
  155. WaitForSingleObject(curThread, INFINITE);
  156. GetExitCodeThread(curThread, &exitCode);
  157. removeModInfo(mod_name);
  158. DbgWithLink_sphost("%s entity exit success", mod_name);
  159. }
  160. */
  161. ReleaseMutex(curMutex);
  162. CloseHandle(curMutex);
  163. return exitCode;
  164. }
  165. DWORD cpuMask[15] = { 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000};
  166. void SetCurrentProcessMask()
  167. {
  168. unsigned long lProcessAffinityMask = 0;
  169. unsigned long lSystemAffinityMask = 0;
  170. int MaxCoreNum = 0;
  171. HANDLE hCurrentProc = GetCurrentProcess();
  172. GetProcessAffinityMask(hCurrentProc, &lProcessAffinityMask, &lSystemAffinityMask);
  173. lProcessAffinityMask = lSystemAffinityMask & 0xFFFFFFFE;
  174. while (lSystemAffinityMask > 0)
  175. {
  176. lSystemAffinityMask = lSystemAffinityMask >> 1;
  177. MaxCoreNum++;
  178. if (MaxCoreNum > 16)
  179. break;
  180. }
  181. if (MaxCoreNum < 4)
  182. return;//小于4核不做相应限制
  183. srand((unsigned int)time(NULL));
  184. //lProcessAffinityMask = 1 << (rand() % (MaxCoreNum - 1) + 1);
  185. //DbgWithLink_sphost("lProcessAffinityMask:%u, MaxCoreNum:%d", lProcessAffinityMask, MaxCoreNum);
  186. SetProcessAffinityMask(hCurrentProc, lProcessAffinityMask);
  187. SetProcessAffinityUpdateMode(hCurrentProc, PROCESS_AFFINITY_ENABLE_AUTO_UPDATE);
  188. //SetPriorityClass(hCurrentProc, NORMAL_PRIORITY_CLASS);
  189. CloseHandle(hCurrentProc);
  190. }
  191. #endif //RVC_OS_WIN
  192. int main(int argc, char *argv[])
  193. {
  194. #ifdef RVC_OS_WIN
  195. char readBuf[MAX_PATH] = "";
  196. char writeBuf[MAX_PATH] = "";
  197. DWORD dwRead = 0;
  198. DWORD dwWrite = 0;
  199. HANDLE hPipe, hMutex, mainThread;
  200. TCHAR chBuf[MAX_PATH] = "";
  201. DWORD dwMode = PIPE_READMODE_MESSAGE;
  202. char lpszPipename[MAX_PATH] = "\\\\.\\pipe\\";
  203. char eventName[MAX_PATH] = "";
  204. DWORD dstShellId = 0;
  205. clock_t t_begin;
  206. int testDua1 = 0, testDual2 = 0, testDual3 = 0, testDual4 = 0, testDual5 = 0, testDual6 = 0;
  207. t_begin = clock();
  208. threadRunLock = CreateEvent(NULL, FALSE, FALSE, NULL);
  209. _CrtSetDebugFillThreshold( 0 );
  210. testDua1 = (clock() - t_begin) * 1000 / CLOCKS_PER_SEC;
  211. t_begin = clock();
  212. /* return shm range */
  213. if (argc == 2) {
  214. if (argv[1][0] == '{')
  215. sprintf(lpszPipename, "%s%s", lpszPipename, argv[1]);
  216. else
  217. {
  218. int range = atoi(argv[1]);
  219. return sp_shm_get_range(range);
  220. }
  221. }
  222. else if (argc == 3) {
  223. if (argv[1][0] == '{') {
  224. dstShellId = atoi(argv[2]);
  225. sprintf(lpszPipename, "%s%s", lpszPipename, argv[1]);
  226. }
  227. else
  228. {
  229. int range = atoi(argv[1]);
  230. return sp_shm_get_range(range);
  231. }
  232. }
  233. testDual2 = (clock() - t_begin) * 1000 / CLOCKS_PER_SEC;
  234. t_begin = clock();
  235. setlocale(LC_ALL, "chs");
  236. #else
  237. int range;
  238. char* mod_name;
  239. int epid;
  240. int rc;
  241. int idx;
  242. char epid_str[64];
  243. for (idx = 0; idx < argc; ++idx) {
  244. printf("argv[%d]: %s\n", idx, argv[idx]);
  245. }
  246. if (argc == 2) {
  247. /* return shm range */
  248. int range = atoi(argv[1]);
  249. printf("range mask: %d\n", range);
  250. range = sp_shm_get_range(range);
  251. printf("range return: %d\n", range);
  252. return range;
  253. }
  254. if (NULL == setlocale(LC_ALL, "zh_CN.UTF-8")) {
  255. //zh_CN.UTF-8 zh_CN.GBK
  256. printf("setlocale failed: %s", strerror(errno));
  257. }
  258. #endif //RVC_OS_WIN
  259. #ifdef RVC_OS_WIN
  260. hPipe = CreateFile(lpszPipename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  261. if (hPipe == INVALID_HANDLE_VALUE && !WaitNamedPipe(lpszPipename, 5000))
  262. return -1;
  263. if (!SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL))
  264. return -1;
  265. testDual3 = (clock() - t_begin) * 1000 / CLOCKS_PER_SEC;
  266. t_begin = clock();
  267. hMutex = OpenEvent(EVENT_ALL_ACCESS, FALSE, argv[1]);
  268. SetEvent(hMutex);
  269. //CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&sphostMonitor, dstShellId, 0, NULL));// 监控内存及句柄线程,进程结束时关闭
  270. testDual4 = (clock() - t_begin) * 1000 / CLOCKS_PER_SEC;
  271. t_begin = clock();
  272. while (ReadFile(hPipe, readBuf, sizeof(readBuf), &dwRead, NULL))
  273. {
  274. char tempBuf[MAX_PATH] = "";
  275. char dstParam[10][MAX_PATH];
  276. int paramNum = 0;
  277. ZeroMemory(dstParam, sizeof(dstParam));
  278. if (-1 == (paramNum = paramSplit(readBuf, dstParam)))
  279. continue;
  280. if (!strcmp(dstParam[0], "start") && paramNum == 7)
  281. {//start
  282. mod_runInfo *curModInfo = (mod_runInfo*)malloc(sizeof(mod_runInfo));
  283. ZeroMemory(curModInfo, sizeof(mod_runInfo));
  284. strcpy(curModInfo->mod_name, dstParam[1]);
  285. curModInfo->epid = atoi(dstParam[2]);
  286. curModInfo->range = atoi(dstParam[3]);
  287. strcpy(curModInfo->modMutexName, dstParam[4]);
  288. curModInfo->group = 0;
  289. g_saveFile = atoi((dstParam[5]));
  290. setCurEntityIdx(atoi(dstParam[6]));
  291. //WLog_initRVC(dstParam[1]);
  292. createLogProducer(dstParam[1], dstParam[2]);
  293. if (testDua1 > 100 || testDual2 > 100 || testDual3 > 100 || testDual4 > 100)
  294. DbgWithLink_sphost("sphost initTest in %d-%d-%d-%d", testDua1, testDual2, testDual3, testDual4);
  295. DbgWithLink_sphost("sphost main start process id: %d, query Entity %s start, epid:%d, range:%d, group:%d", GetCurrentProcessId(), curModInfo->mod_name, curModInfo->epid, curModInfo->range, curModInfo->group);
  296. mainThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&runThreadAndMonitor, curModInfo, 0, &curModInfo->threadId);
  297. testDual5 = (clock() - t_begin) * 1000 / CLOCKS_PER_SEC;
  298. t_begin = clock();
  299. if(testDual5 > 100)
  300. DbgWithLink_sphost("%s entity main, Wait threadRunLock, cost %d", curModInfo->mod_name, testDual5);
  301. if (WAIT_TIMEOUT == WaitForSingleObject(threadRunLock, 4500)) //wait for entity thread create
  302. {
  303. WriteFile(hPipe, OPERATE_FAIL, strlen(OPERATE_FAIL) + 1, &dwWrite, NULL);
  304. DbgWithLink_sphost("%s entity run timeout!", curModInfo->mod_name);
  305. }
  306. else if (NULL != curModInfo->threadHandle)
  307. {
  308. WriteFile(hPipe, OPERATE_SUCCESS, strlen(OPERATE_SUCCESS) + 1, &dwWrite, NULL);
  309. testDual6 = (clock() - t_begin) * 1000 / CLOCKS_PER_SEC;
  310. t_begin = clock();
  311. if(testDual6 > 100)
  312. DbgWithLink_sphost("%s entity run success, cost %d!", curModInfo->mod_name, testDual6);
  313. SetCurrentProcessMask();
  314. CloseHandle(mainThread);
  315. CloseHandle(hMutex);
  316. }
  317. else
  318. {
  319. WriteFile(hPipe, OPERATE_FAIL, strlen(OPERATE_FAIL) + 1, &dwWrite, NULL);
  320. DbgWithLink_sphost("%s entity run failed!", curModInfo->mod_name);
  321. }
  322. /*
  323. if (!g_entityStart) {
  324. g_entityStart = 1;
  325. CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&sphostMonitor, NULL, 0, NULL)); // 监控内存及句柄线程,进程结束时关闭
  326. }*/
  327. }
  328. else if(!strcmp(dstParam[0], "kill") && paramNum == 2)
  329. {
  330. //kill
  331. mod_runInfo* killModInfo = NULL;
  332. DbgWithLink_sphost("pipe kill %s", dstParam[1]);
  333. killModInfo = queryModInfo(dstParam[1]);
  334. if (NULL != killModInfo)
  335. {
  336. static mod_exitInfo curModInfo;
  337. HANDLE tmpHandle;
  338. sprintf_s(curModInfo.mod_name, sizeof(curModInfo.mod_name), "%s", killModInfo->mod_name);
  339. tmpHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&SpExit, &curModInfo, 0, NULL);
  340. if (tmpHandle != NULL) { CloseHandle(tmpHandle); }
  341. if (WAIT_TIMEOUT != WaitForSingleObject(killModInfo->threadHandle, DEFAULT_WAITENTITY_END))
  342. WriteFile(hPipe, OPERATE_SUCCESS, strlen(OPERATE_SUCCESS) + 1, &dwWrite, NULL);
  343. else
  344. WriteFile(hPipe, OPERATE_FAIL, strlen(OPERATE_FAIL) + 1, &dwWrite, NULL);
  345. //监控线程自动清理
  346. } else if (!strcmp(dstParam[1], "process")) {
  347. WriteFile(hPipe, OPERATE_SUCCESS, strlen(OPERATE_SUCCESS) + 1, &dwWrite, NULL);
  348. DbgWithLink_sphost("tell spshell the operation is done and exit process directly.");
  349. return 0;
  350. } else {
  351. WriteFile(hPipe, OPERATE_FAIL, strlen(OPERATE_FAIL) + 1, &dwWrite, NULL);
  352. }
  353. }
  354. else if (!strcmp(dstParam[0], "query") && paramNum == 2)
  355. {//查询特定实体Info
  356. const mod_runInfo *queryInfo = queryModInfo(dstParam[1]);
  357. if (NULL != queryInfo)
  358. {
  359. sprintf_s(tempBuf, sizeof(tempBuf), "%s %s %s %d", OPERATE_SUCCESS, queryInfo->mod_name, queryInfo->modMutexName, queryInfo->threadId);//threadId对于远程进程并无任何用途
  360. WriteFile(hPipe, tempBuf, strlen(tempBuf) + 1, &dwWrite, NULL);
  361. }
  362. else
  363. WriteFile(hPipe, OPERATE_FAIL, strlen(OPERATE_FAIL) + 1, &dwWrite, NULL);
  364. }
  365. }
  366. #else
  367. range = atoi(argv[1]);
  368. mod_name = argv[2];
  369. epid = atoi(argv[3]);
  370. g_saveFile = atoi((argv[4]));
  371. sprintf(epid_str, "%d", epid);
  372. setCurEntityIdx(atoi(argv[5]));
  373. if (!mod_name || !strlen(mod_name)) {
  374. return -300;
  375. }
  376. WLog_initRVC(mod_name);
  377. createLogProducer(mod_name, epid_str);
  378. SetEnvPath(mod_name);
  379. rc = SpRun(mod_name, epid, range, 0, g_saveFile);
  380. #endif //RVC_OS_WIN
  381. return 0;
  382. }
  383. #ifdef RVC_OS_WIN
  384. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  385. {
  386. return main(__argc, __argv);
  387. }
  388. #endif //RVC_OS_WIN