guardian.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590
  1. // guardian.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #ifdef linux
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <sys/socket.h>
  8. #include <sys/epoll.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <assert.h>
  12. #include <dirent.h>
  13. #include <fcntl.h>
  14. #include <unistd.h>
  15. #include <stdio.h>
  16. #include <errno.h>
  17. #include <string.h>
  18. #include <syslog.h>
  19. #include <signal.h>
  20. #include <pthread.h>
  21. #include <pwd.h>
  22. #include <signal.h>
  23. #include <sys/types.h>
  24. #include <sys/wait.h>
  25. #include "toolkit.h"
  26. #include "osutil.h"
  27. #include "memutil.h"
  28. #include <winpr/library.h>
  29. #include <winpr/synch.h>
  30. #include <winpr/sysinfo.h>
  31. #include <winpr/environment.h>
  32. int epfd;
  33. struct epoll_event ev;
  34. #define MAXLINE 128
  35. #define OPEN_MAX 100
  36. #define LISTENQ 20
  37. #define INFTIM 1000
  38. #else
  39. #undef UNICODE
  40. #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
  41. #ifndef WIN32_LEAN_AND_MEAN
  42. #define WIN32_LEAN_AND_MEAN
  43. #endif
  44. #include <windows.h>
  45. #include <winsock2.h>
  46. #include <ws2tcpip.h>
  47. #include <TlHelp32.h>
  48. #include <direct.h>
  49. #include <ctime>
  50. #endif //linux
  51. #include <iostream>
  52. #include <fstream>
  53. #include <string>
  54. #include <vector>
  55. #include "GuardianBase.h"
  56. #include "guardian.h"
  57. #include "log4rvcother.h"
  58. #ifndef MAX_PATH
  59. #define MAX_PATH 260
  60. #endif
  61. #define GUARDIAN_VERSION_STR "0.0.2"
  62. #ifdef RVC_OS_WIN
  63. static char spshell_execute_name[] = "SpShell.exe";
  64. static char sphost_execute_name[] = "SpHost.exe";
  65. static char guardian_execute_name[] = "Guardian.exe";
  66. static char cefclient_execute_name[] = "cefclient.exe";
  67. #else
  68. static char spshell_execute_name[] = "spshell";
  69. static char sphost_execute_name[] = "sphost";
  70. static char guardian_execute_name[] = "guardian";
  71. static char cefclient_execute_name[] = "cefclient";
  72. #endif //_WIN32
  73. char* relate_processes[] = { spshell_execute_name };
  74. char* relate_processes_ex[] = { spshell_execute_name, sphost_execute_name, cefclient_execute_name };
  75. using namespace std;
  76. #ifdef linux
  77. int g_sListen;
  78. pthread_mutex_t g_cs, g_cs_event, g_cs_log;
  79. #define EnterCriticalSectionRVC(xType) pthread_mutex_lock(&xType)
  80. #define LeaveCriticalSectionRVC(xType) pthread_mutex_unlock(&xType)
  81. static int GetProcID()
  82. {
  83. return getpid();
  84. }
  85. #else
  86. SOCKET g_sListen = INVALID_SOCKET;
  87. DWORD WINAPI DoNetControl(void* pData);
  88. CRITICAL_SECTION g_cs, g_cs_event, g_cs_log;
  89. #define EnterCriticalSectionRVC(xType) EnterCriticalSection(&xType)
  90. #define LeaveCriticalSectionRVC(xType) LeaveCriticalSection(&xType)
  91. static int GetProcID()
  92. {
  93. return GetCurrentProcessId();
  94. }
  95. #endif //linux
  96. const int DEFAULT_BUFLEN = 512;
  97. const int SHAKEHAND_BUFZIE = 32;
  98. #define DEFAULT_PORT "30005"
  99. const int default_port = 30005;
  100. int g_needToRollBack = 0;
  101. bool g_needUpgradeGuardianOnly = false;
  102. bool g_bFrameQuit = false,g_bFrameOnline = false,g_bAuthSuc = false,g_bInUpgrade = false;
  103. ULONGLONG g_dwTimeBegin = 0;
  104. ULONGLONG g_dwUpgradeRestartTimeBegin = 0;
  105. int cnt = 0;
  106. char chDisk[2];
  107. char currDirBuf[256];
  108. const int MAX_WAIT_TIME_TO_RESTART = 600000;
  109. //oilyang@20211208 change value from 110000 to 180000
  110. const int MAX_WAIT_TIME_TO_RESTART_UPGRADE = 180000;
  111. static int g_SpShellPID = 0;
  112. #ifdef linux
  113. extern "C"
  114. {
  115. void* DoWorkLinux(void* arg);
  116. void* DoNetControlLinux(void* arg);
  117. }
  118. #define FUNCTION_STDCALL
  119. typedef unsigned short WORD;
  120. #else
  121. typedef struct
  122. {
  123. OVERLAPPED Overlapped;
  124. WSABUF DataBuf;
  125. CHAR Buffer[DATA_BUFSIZE];
  126. } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
  127. typedef struct
  128. {
  129. SOCKET Socket;
  130. } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
  131. DWORD WINAPI DoWork(void* pData);
  132. #define FUNCTION_STDCALL __stdcall
  133. #endif
  134. int BeginThreadRVC(void* (*pFuncLinux)(void*), LPTHREAD_START_ROUTINE pFuncWin)
  135. {
  136. #if defined(_MSC_VER)
  137. CreateThread(NULL, 0, pFuncWin, NULL, 0, NULL);
  138. return 0;
  139. #else
  140. pthread_t tidp;
  141. if ((pthread_create(&tidp, NULL, pFuncLinux, NULL) == -1)) {
  142. return 1;
  143. }
  144. cout << "after pthread_create of linux thread" << endl;
  145. return 0;
  146. #endif //_MSC_VER
  147. }
  148. void EndThreadRVC()
  149. {
  150. #ifdef linux
  151. pthread_exit(0);
  152. #endif //linux
  153. }
  154. void StartDoNetControlRVC()
  155. {
  156. #ifdef linux
  157. BeginThreadRVC(DoNetControlLinux, NULL);
  158. #else
  159. BeginThreadRVC(NULL, DoNetControl);
  160. #endif //linux
  161. }
  162. void StartDoWorkRVC()
  163. {
  164. #ifdef linux
  165. BeginThreadRVC(DoWorkLinux, NULL);
  166. #else
  167. BeginThreadRVC(NULL, DoWork);
  168. #endif //linux
  169. }
  170. void ServerReportEvent(const char* szFunction,const char* szName="guardian")
  171. {
  172. #ifdef linux
  173. return;//oiltest
  174. #else
  175. HANDLE hEventSource;
  176. LPCTSTR lpszStrings[2];
  177. char Buffer[1024] = {0};
  178. hEventSource = RegisterEventSource(NULL, szName);
  179. if( NULL != hEventSource )
  180. {
  181. strcpy_s(Buffer,1024,szFunction);
  182. lpszStrings[0] = szName;
  183. lpszStrings[1] = Buffer;
  184. ReportEvent(hEventSource, // event log handle
  185. EVENTLOG_ERROR_TYPE, // event type
  186. 0, // event category
  187. 0xe0000001, // event identifier
  188. NULL, // no security identifier
  189. 2, // size of lpszStrings array
  190. 0, // no binary data
  191. lpszStrings, // array of strings
  192. NULL); // no binary data
  193. DeregisterEventSource(hEventSource);
  194. }
  195. #endif //linux
  196. }
  197. bool VersionRollback()
  198. {
  199. const int VersionLenMax = 64;
  200. fstream verFile,verBak;//to confirm
  201. string strActiveTxtPath, strVersionDatPath;
  202. #ifdef linux
  203. char tmp[MAX_PATH];
  204. char* pos = NULL;
  205. GetModuleFileNameA(NULL, tmp, MAX_PATH);
  206. LOG4VTM(INFO, "rollback" << tmp);
  207. if ((pos = strstr(tmp, "/Run/")) != NULL) {
  208. pos[strlen("/Run/")] = '\0';
  209. strActiveTxtPath = string(tmp) + "version/active.txt";
  210. strVersionDatPath = string(tmp) + "runinfo/runcfg/version.dat";
  211. }
  212. else {
  213. strActiveTxtPath = "/opt/Run/version/active.txt";
  214. strVersionDatPath = "/opt/Run/runinfo/runcfg/version.dat";
  215. }
  216. #else
  217. string strDisk(chDisk);
  218. strActiveTxtPath = strDisk + ":\\Run\\version\\active.txt";
  219. strVersionDatPath = strDisk + ":\\Run\\runinfo\\runcfg\\version.dat";
  220. #endif //linux
  221. verFile.open(strActiveTxtPath,std::fstream::in|std::fstream::out|std::fstream::binary);
  222. verBak.open(strVersionDatPath,std::fstream::in|std::fstream::out|std::fstream::binary);
  223. if (!verFile.is_open() || !verBak.is_open())
  224. return false;
  225. char *pVerBak,*pNULL,*pCurrVer;
  226. pVerBak = new char[VersionLenMax];
  227. pNULL = new char[VersionLenMax];
  228. pCurrVer = new char[VersionLenMax];
  229. memset(pVerBak,0,VersionLenMax);
  230. memset(pNULL,0,VersionLenMax);
  231. memset(pCurrVer,0,VersionLenMax);
  232. verBak.seekg(0,verBak.end);
  233. int lenBak = verBak.tellg();
  234. verBak.seekg(0,verBak.beg);
  235. verBak.read(pVerBak,lenBak);
  236. //need to consider atomic op? oilyang
  237. verFile.seekg(0,verFile.end);
  238. int len = verFile.tellg();
  239. verFile.seekg(0,verFile.beg);
  240. verFile.read(pCurrVer,len);
  241. LOG4VTM(INFO, pVerBak);
  242. LOG4VTM(INFO, pCurrVer);
  243. LOG4VTM(INFO, pNULL);
  244. if (strcmp(pVerBak,pCurrVer) == 0)
  245. {
  246. ServerReportEvent(pVerBak);
  247. verFile.close();
  248. verBak.close();
  249. delete []pVerBak;
  250. delete []pNULL;
  251. return false;
  252. }
  253. //verBak.write(pNULL,len);
  254. //verFile.write(pNULL,len);
  255. //how foolish?
  256. verFile.close();
  257. verFile.open(strActiveTxtPath,std::fstream::in|std::fstream::out|std::fstream::binary|std::fstream::trunc);
  258. verFile.seekg(0,verFile.beg);
  259. verFile.write(pVerBak,lenBak);
  260. LOG4VTM(INFO, "terminal app version will rollback from " << pCurrVer << " to " << pVerBak);
  261. verFile.close();
  262. verBak.close();
  263. delete []pVerBak;
  264. delete []pNULL;
  265. return true;
  266. }
  267. #ifndef _WIN32
  268. static int GetSpshellProcID()
  269. {
  270. int result(0);
  271. char* spshell[] = { spshell_execute_name };
  272. alive_process_info processes[1];
  273. memset(processes, 0, sizeof(processes));
  274. int count = 1;
  275. if (!osutil_detect_unique_app(spshell, array_size(spshell), &count, processes)) {
  276. result = processes[0].pid;
  277. }
  278. return result;
  279. }
  280. static void ComfirmSpShellDead()
  281. {
  282. char* spshell[] = { spshell_execute_name };
  283. alive_process_info processes[1];
  284. memset(processes, 0, sizeof(processes));
  285. int count = 1;
  286. if (!osutil_detect_unique_app(spshell, array_size(spshell), &count, processes)) {
  287. if(g_SpShellPID == 0) g_SpShellPID = processes[0].pid;
  288. LOG4VTM(WARN, "has spshell process alive! and to kill it");
  289. assert(count > 0);
  290. if (kill(processes[0].pid, SIGTERM) != 0) {
  291. LOG4VTM(WARN, "kill with term for spshell failed, process id: " << processes[0].pid << ", err: " << errno);
  292. if (errno != 3 /**not exist */) {
  293. LOG4VTM(INFO, "to kill stronglely!");
  294. kill(processes[0].pid, SIGKILL);
  295. }
  296. } else {
  297. LOG4VTM(DEBUG, "kill with term for spshell succ. process id: " << processes[0].pid);
  298. }
  299. const int waitTimes = 100;
  300. const int eachTime = 300;
  301. int curTimes = 0;
  302. while (g_SpShellPID != 0 && curTimes < waitTimes) {
  303. if (osutil_detect_unique_app(spshell, array_size(spshell), NULL, NULL)) {
  304. g_SpShellPID = 0;
  305. break;
  306. }
  307. Sleep(eachTime);
  308. curTimes++;
  309. }
  310. if (g_SpShellPID == 0) {
  311. LOG4VTM(DEBUG, "spshell has gone!");
  312. }
  313. } else {
  314. LOG4VTM(INFO, "There are no any spshell process existed!");
  315. }
  316. //////////////////////////////////////////////////////////////////////////
  317. count = MAX_ALIVE_PROCESS_COUNT;
  318. alive_process_info processes2[MAX_ALIVE_PROCESS_COUNT];
  319. memset(processes2, 0, sizeof(processes2));
  320. if (!osutil_detect_unique_app(relate_processes_ex, array_size(relate_processes_ex), &count, processes2)) {
  321. for (int i = 0; i < count; ++i) {
  322. LOG4VTM(INFO, processes2[i].name << " " << processes2[i].path << " " << processes2[i].pid);
  323. }
  324. osutil_terminate_related_process(relate_processes_ex, array_size(relate_processes_ex), 0);
  325. Sleep(1000);
  326. }
  327. }
  328. inline static std::vector<std::string> Split(std::string str, char splitElem)
  329. {
  330. std::vector<std::string> strs;
  331. std::string::size_type pos1, pos2;
  332. pos2 = str.find(splitElem);
  333. pos1 = 0;
  334. while (std::string::npos != pos2) {
  335. strs.push_back(str.substr(pos1, pos2 - pos1));
  336. pos1 = pos2 + 1;
  337. pos2 = str.find(splitElem, pos1);
  338. }
  339. strs.push_back(str.substr(pos1));
  340. return strs;
  341. }
  342. static bool IsSpPathType(const std::string& value)
  343. {
  344. const int leastLength = strlen("Run/version/1.0.0.0/");
  345. std::string path(value.c_str());
  346. if (path.empty() || path.size() < leastLength) return false;
  347. const std::size_t sionPos = path.find("version");
  348. const std::size_t verPos = sionPos + strlen("version\\");
  349. if (sionPos == std::string::npos) return false;
  350. std::size_t suffixPos = std::string::npos, i;
  351. std::size_t dotCnt = 0;
  352. bool lastIsNum = false;
  353. for (i = verPos; i < path.size() && (path[i] >= '0' && path[i] <= '9' || path[i] == '.'); ++i) {
  354. lastIsNum = !(path[i] == '.');
  355. if (!lastIsNum) dotCnt++;
  356. }
  357. if (i >= path.size() || dotCnt != 3 || !lastIsNum)
  358. return false;
  359. return true;
  360. }
  361. /** 移除跟版本目录相关的环境变量信息*/
  362. static std::string CutSpPathFromPathValue(const char* value)
  363. {
  364. std::string path(value);
  365. std::string result("");
  366. std::vector<std::string> values = Split(path, ':');
  367. if (values.size() <= 0) {
  368. return path;
  369. }
  370. for (auto i = values.cbegin(); i != values.cend(); i++) {
  371. if (!IsSpPathType(*i)) {
  372. if (!result.empty()) result += ":";
  373. result += (*i);
  374. }
  375. }
  376. if (!result.empty() && path[path.size() - 1] == ':') {
  377. result += ":";
  378. }
  379. return result;
  380. }
  381. static void ResetEnviromentVars(const char* env)
  382. {
  383. DWORD size;
  384. char* buf;
  385. int len = 0;
  386. size = GetEnvironmentVariableA(env, NULL, 0);
  387. if (size == 0) {
  388. return;
  389. }
  390. len = size + MAX_PATH * 3;
  391. buf = (char*)malloc(len);
  392. memset(buf, 0, sizeof(buf));
  393. size = GetEnvironmentVariableA(env, buf, len);
  394. std::string newValue = CutSpPathFromPathValue(buf);
  395. if (newValue.empty()) {
  396. SetEnvironmentVariableA(env, NULL);
  397. } else if (newValue.size() < size) {
  398. strcpy(buf, newValue.c_str());
  399. SetEnvironmentVariableA(env, buf);
  400. }
  401. #if 1
  402. memset(buf, 0, sizeof(buf));
  403. size = GetEnvironmentVariableA(env, buf, len);
  404. LOG4VTM(INFO, buf << "env: " << env << " size: " << size);
  405. #endif
  406. FREE(buf);
  407. }
  408. static void ResetRelateEnviromentVars( const char* prefix)
  409. {
  410. LOG4VTM(INFO, prefix);
  411. ResetEnviromentVars("LD_LIBRARY_PATH");
  412. ResetEnviromentVars("PATH");
  413. }
  414. #endif //NOT _WIN32
  415. int FrameworkShutdown(bool bUpgrade=false,bool bRestart = true)
  416. {
  417. LOG4VTM(INFO, "in FrameworkShutdown,bUpgrade:" << bUpgrade << ",bRestart:" << bRestart);
  418. if (!bUpgrade)
  419. g_dwTimeBegin = GetTickCount64();
  420. #ifdef linux
  421. //todo oiltestlinux
  422. LOG4VTM(DEBUG, "to kill spshell");
  423. ServerReportEvent("FrameworkShutdown linux");
  424. ComfirmSpShellDead();
  425. char tmp[MAX_PATH];
  426. char* pos = NULL;
  427. GetModuleFileNameA(NULL, tmp, MAX_PATH);
  428. LOG4VTM(INFO, "FrameworkShutdown: " << tmp);
  429. if ((pos = strstr(tmp, "/version")) != NULL) {
  430. pos[strlen("/version")+1] = '\0';
  431. ResetRelateEnviromentVars(tmp);
  432. char path[MAX_PATH] = { '\0' };
  433. bool toResetCWD(false);
  434. LOG4VTM(DEBUG, "to get current directory...");
  435. GetCurrentDirectoryA(MAX_PATH, path);
  436. LOG4VTM(DEBUG, path);
  437. if (strlen(path) <= 0 || strcmp(path, tmp) != 0) {
  438. LOG4VTM(INFO, "to set current directory...");
  439. SetCurrentDirectoryA(tmp);
  440. toResetCWD = true;
  441. }
  442. strcat(tmp, "spexplorer.sh --restart");
  443. LOG4VTM(DEBUG, tmp);
  444. tk_process_t* process = NULL;
  445. tk_process_option_t option;
  446. option.exit_cb = NULL;
  447. option.file = NULL;
  448. option.flags = 0;
  449. option.params = tmp;
  450. if (0 == process_spawn(&option, &process)) {
  451. FREE(process);
  452. LOG4VTM(INFO, "run spexplorer.sh scripts succ.");
  453. Sleep(1000);
  454. g_SpShellPID = GetSpshellProcID();
  455. LOG4VTM(INFO, "get spshell proc id: " << g_SpShellPID);
  456. if (toResetCWD) {
  457. SetCurrentDirectoryA(path);
  458. }
  459. return 0;
  460. } else {
  461. FREE(process);
  462. LOG4VTM(ERROR, "run spexplorer.sh scripts failed!");
  463. if (toResetCWD) {
  464. SetCurrentDirectoryA(path);
  465. }
  466. return -1;
  467. }
  468. }
  469. LOG4VTM(WARN, "get regular version path failed!");
  470. return 0;
  471. #else
  472. STARTUPINFO si;
  473. PROCESS_INFORMATION pi;
  474. ZeroMemory( &si, sizeof(si) );
  475. si.cb = sizeof(si);
  476. ZeroMemory( &pi, sizeof(pi) );
  477. // Start the child process.
  478. std::string csRestart,csVerPath,csAll,csSep("\""),csBlank(" "),csScript("wscript.exe"),csReFlag("r");
  479. csRestart = "sprestart.exe ";
  480. csVerPath = chDisk;
  481. csVerPath = csVerPath + std::string(":\\Run\\version");
  482. csVerPath = csVerPath + std::string("\\VTM.exe");
  483. if (!bRestart)
  484. csReFlag = "n";
  485. csAll = csSep + csRestart + csSep + csBlank + csSep + csVerPath + csSep
  486. + csBlank + csSep + csReFlag + csSep;
  487. char* szCmdline = new char[csAll.length() + 1];
  488. memset(szCmdline, '\0', csAll.length() + 1);
  489. strcpy(szCmdline, csAll.c_str());
  490. if( !CreateProcess( NULL,szCmdline,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
  491. {
  492. delete[] szCmdline;
  493. return -1;
  494. }
  495. DWORD dwErr = GetLastError();
  496. // Wait until child process exits.
  497. WaitForSingleObject( pi.hProcess, INFINITE );
  498. // Close process and thread handles.
  499. CloseHandle( pi.hProcess );
  500. CloseHandle( pi.hThread );
  501. delete[] szCmdline;
  502. return 0;
  503. #endif //linux
  504. }
  505. bool FrameworkRollBack()
  506. {
  507. bool bVerRollback = VersionRollback();
  508. LOG4VTM(INFO, "version rollback ");
  509. if (true)
  510. FrameworkShutdown();
  511. return true;
  512. }
  513. bool ReadRuninfoContent(string &strData)
  514. {
  515. fstream runinfo;
  516. string strGdRuninfoPath;
  517. #ifdef linux
  518. //todo oiltestlinux
  519. char tmp[MAX_PATH];
  520. char* pos = NULL;
  521. GetModuleFileNameA(NULL, tmp, MAX_PATH);
  522. if ((pos = strstr(tmp, "/Run/")) != NULL) {
  523. pos[strlen("/Run/")] = '\0';
  524. strGdRuninfoPath = string(tmp) + "runinfo/runcfg/gdruninfo";
  525. }
  526. else {
  527. strGdRuninfoPath = "/opt/Run/runinfo/runcfg/gdruninfo";
  528. }
  529. #else
  530. string strDisk(chDisk);
  531. strGdRuninfoPath = strDisk + ":\\Run\\runinfo\\runcfg\\gdruninfo";
  532. #endif //linux
  533. LOG4VTM(INFO, strGdRuninfoPath.c_str());
  534. runinfo.open(strGdRuninfoPath,std::fstream::in|std::fstream::out|std::fstream::binary);
  535. if (!runinfo.is_open())
  536. {
  537. LOG4VTM(INFO, "open gdruninfo(read) failed.");
  538. return false;
  539. }
  540. runinfo.seekg(0,ios::end);
  541. int size = runinfo.tellg();
  542. if (size <= 0)
  543. return false;
  544. char *pData = new char[size+1];
  545. memset(pData,0,size+1);
  546. runinfo.seekg(0,ios::beg);
  547. runinfo.read(pData,size);
  548. strData = string(pData);
  549. LOG4VTM(INFO, "read runinfo " << strData);
  550. return true;
  551. }
  552. bool WriteRunInfoContent(const char* pData)
  553. {
  554. ofstream runinfo;
  555. string strGdRuninfoPath;
  556. #ifdef linux
  557. //todo oiltestlinux
  558. char tmp[MAX_PATH];
  559. char* pos = NULL;
  560. GetModuleFileNameA(NULL, tmp, MAX_PATH);
  561. LOG4VTM(INFO, tmp);
  562. if ((pos = strstr(tmp, "/Run/")) != NULL) {
  563. pos[strlen("/Run/")] = '\0';
  564. strGdRuninfoPath = string(tmp) + "runinfo/runcfg/gdruninfo";
  565. }
  566. else {
  567. strGdRuninfoPath = "/opt/Run/runinfo/runcfg/gdruninfo";
  568. }
  569. LOG4VTM(INFO, strGdRuninfoPath.c_str());
  570. #else
  571. string strDisk(chDisk);
  572. strGdRuninfoPath = strDisk + ":\\Run\\runinfo\\runcfg\\gdruninfo";
  573. #endif //linux
  574. runinfo.open(strGdRuninfoPath,std::ofstream::in|std::ofstream::binary|std::ofstream::trunc);
  575. if (!runinfo.is_open())
  576. {
  577. LOG4VTM(INFO, "open gdruninfo(write) failed.");
  578. ServerReportEvent("open gdruninfo(write) failed.");
  579. return false;
  580. }
  581. runinfo.write(pData,strlen(pData));
  582. runinfo.close();
  583. LOG4VTM(INFO, "write " << strGdRuninfoPath << " done");
  584. return true;
  585. }
  586. bool IsStartTimeFileExist()
  587. {
  588. ofstream runinfo;
  589. string strStartTimePath;
  590. #ifdef linux
  591. //todo oiltestlinux
  592. char tmp[MAX_PATH];
  593. char* pos = NULL;
  594. GetModuleFileNameA(NULL, tmp, MAX_PATH);
  595. LOG4VTM(INFO, "IsStartTimeFileExist: " << tmp);
  596. if ((pos = strstr(tmp, "/Run/")) != NULL) {
  597. pos[strlen("/Run/")] = '\0';
  598. strStartTimePath = string(tmp) + "runinfo/runcfg/starttime.dat";
  599. }
  600. else {
  601. strStartTimePath = "/opt/Run/runinfo/runcfg/starttime.dat";
  602. }
  603. #else
  604. string strDisk(chDisk);
  605. strStartTimePath = strDisk + ":\\Run\\runinfo\\runcfg\\starttime.dat";
  606. #endif //linux
  607. runinfo.open(strStartTimePath, std::fstream::in | std::fstream::out | std::fstream::binary);
  608. if (!runinfo.is_open()) {
  609. LOG4VTM(ERROR, "open starttime.dat failed");
  610. return false;
  611. }
  612. else
  613. {
  614. runinfo.close();
  615. LOG4VTM(DEBUG, "open starttime.dat succ");
  616. return true;
  617. }
  618. }
  619. #ifdef linux
  620. void CheckDoWork(int sig)
  621. {
  622. cout << "CheckDoWork" << endl;
  623. if (SIGALRM == sig)
  624. {
  625. EnterCriticalSectionRVC(g_cs);
  626. if (!g_bFrameQuit)
  627. {
  628. ULONGLONG dwTmpBegin = g_dwTimeBegin;
  629. ULONGLONG dwUpgradeTmpBegin = g_dwUpgradeRestartTimeBegin;
  630. LeaveCriticalSectionRVC(g_cs);
  631. ULONGLONG dwTimeEnd = GetTickCount64();
  632. //oilyang@20190828 add
  633. //升级重启后,在10分钟内,只要离最后一次交互时间大于2分钟,重启框架
  634. if ((g_bInUpgrade && ((dwTimeEnd - dwUpgradeTmpBegin) < MAX_WAIT_TIME_TO_RESTART))
  635. && (!g_bAuthSuc && ((dwTimeEnd - dwTmpBegin) > MAX_WAIT_TIME_TO_RESTART_UPGRADE)))
  636. {
  637. LOG4VTM(WARN, "**in upgrade restart**,to restart framework(linux).");
  638. FrameworkShutdown(true, true);
  639. }
  640. if ((dwTimeEnd - dwTmpBegin) > MAX_WAIT_TIME_TO_RESTART)
  641. {
  642. LOG4VTM(ERROR, "framework maybe down.");
  643. string strRunInfo;
  644. if (ReadRuninfoContent(strRunInfo))
  645. {
  646. LOG4VTM(INFO, "to check if need rollback.");
  647. LOG4VTM(INFO, (char*)strRunInfo.c_str());
  648. if (strRunInfo.compare("111") == 0 && IsStartTimeFileExist())
  649. {
  650. EnterCriticalSectionRVC(g_cs);
  651. g_needToRollBack = 1;
  652. LeaveCriticalSectionRVC(g_cs);
  653. }
  654. }
  655. else
  656. LOG4VTM(WARN, "read run info failed.");
  657. if (g_needToRollBack)
  658. {
  659. LOG4VTM(INFO, "after upgrade,time elapse,but can't wait the shake hands,so rollback.");
  660. FrameworkRollBack();
  661. }
  662. else
  663. {
  664. //framework is down,to restart it! oilyang 20150413
  665. FrameworkShutdown();
  666. }
  667. }
  668. }
  669. else
  670. LeaveCriticalSectionRVC(g_cs);
  671. alarm(2 * 60); //we contimue set the timer
  672. }
  673. return;
  674. }
  675. void* DoWorkLinux(void* arg)
  676. {
  677. LOG4VTM(DEBUG, "DoWorkLinux");
  678. signal(SIGALRM, CheckDoWork); //relate the signal and function
  679. alarm(2 * 60); //trigger the timer
  680. EndThreadRVC();
  681. }
  682. void* DoNetControlLinux(void* arg)
  683. {
  684. LOG4VTM(DEBUG, "to end DoNetControlLinux");
  685. EndThreadRVC();
  686. LOG4VTM(DEBUG, "after end DoNetControlLinux");
  687. }
  688. void DataProcessLinux(int socket,const char*data)
  689. {
  690. GuardianInfo* pInfo = (GuardianInfo*)data;
  691. LOG4VTM(DEBUG, "eType:" << pInfo->eType << ",p1:" << pInfo->dwParam1 << ",p2:" << pInfo->dwParam2 << ",dwSize:" << pInfo->dwSize);
  692. switch (pInfo->eType)
  693. {
  694. case GdOpShakeHand:
  695. {
  696. if (!g_bFrameOnline)
  697. {
  698. g_bFrameOnline = true;
  699. g_SpShellPID = GetSpshellProcID();
  700. LOG4VTM(INFO, "get spshell proc id" << g_SpShellPID);
  701. StartDoNetControlRVC();
  702. }
  703. int rc, err;
  704. EnterCriticalSectionRVC(g_cs);
  705. g_bFrameQuit = false;
  706. g_dwTimeBegin = GetTickCount64();
  707. LeaveCriticalSectionRVC(g_cs);
  708. char* pBuf = new char[8];
  709. memset(pBuf, 0, 8);
  710. //get guardian state
  711. //ex:u(update),g(guardian),r(reboot),b(rollback)
  712. if (cnt % 2 == 0)
  713. memcpy(pBuf, "g", 1);
  714. else
  715. memcpy(pBuf, "u", 1);
  716. cnt++;
  717. rc = send(socket, pBuf, 8, 0);
  718. delete[]pBuf;
  719. close(socket);
  720. }
  721. break;
  722. case GdOpUpdateTask:
  723. {
  724. if (!g_bFrameOnline)
  725. {
  726. g_bFrameOnline = true;
  727. g_SpShellPID = GetSpshellProcID();
  728. LOG4VTM(INFO, "get spshell proc id" << g_SpShellPID);
  729. StartDoNetControlRVC();
  730. }
  731. }
  732. break;
  733. case GdOpQueryInstall:
  734. {
  735. if (!g_bFrameOnline)
  736. {
  737. g_bFrameOnline = true;
  738. g_SpShellPID = GetSpshellProcID();
  739. LOG4VTM(INFO, "get spshell proc id" << g_SpShellPID);
  740. StartDoNetControlRVC();
  741. }
  742. int rc, err;
  743. char* pBuf = new char[8];
  744. memset(pBuf, 0, 8);
  745. if (cnt % 2 == 0)
  746. memcpy(pBuf, "y", 1);
  747. else
  748. memcpy(pBuf, "n", 1);
  749. cnt++;
  750. rc = send(socket, pBuf, 8, 0);
  751. delete[]pBuf;
  752. close(socket);
  753. }
  754. break;
  755. case GdOpUpgradeRestart:
  756. {
  757. if (pInfo->dwParam1 == 6)//HealthManager call guardian to quit
  758. {
  759. LOG4VTM(INFO, "HealthManager call guardian to quit");
  760. close(socket);
  761. close(g_sListen);
  762. exit(0);//baoli?
  763. break;
  764. }
  765. if (pInfo->dwParam1 == 4)//just know framework is starting...
  766. {
  767. LOG4VTM(INFO, "framework is starting...");
  768. g_bFrameOnline = true;
  769. g_SpShellPID = GetSpshellProcID();
  770. LOG4VTM(INFO, "get spshell proc id" << g_SpShellPID);
  771. g_bAuthSuc = false;
  772. StartDoNetControlRVC();
  773. LOG4VTM(DEBUG, "to break upgrade...");
  774. close(socket);
  775. break;
  776. }
  777. if (pInfo->dwParam1 == 5)
  778. {
  779. LOG4VTM(INFO, "framework auth ok.");
  780. g_bInUpgrade = false;
  781. g_bAuthSuc = true;
  782. }
  783. if (!g_bFrameOnline)
  784. {
  785. g_bFrameOnline = true;
  786. g_SpShellPID = GetSpshellProcID();
  787. LOG4VTM(INFO, "get spshell proc id" << g_SpShellPID);
  788. StartDoNetControlRVC();
  789. }
  790. if (pInfo->dwParam1 == 1 || pInfo->dwParam1 == 3)
  791. g_dwTimeBegin = GetTickCount64();
  792. ServerReportEvent("upgrade restart");
  793. LOG4VTM(INFO, "upgrade restart " << pInfo->dwParam1);
  794. if (pInfo->dwParam1 == 1)//framework to restart after upgrade
  795. {
  796. g_bInUpgrade = true;
  797. WriteRunInfoContent("111");
  798. g_dwUpgradeRestartTimeBegin = GetTickCount64();
  799. }
  800. else if (pInfo->dwParam1 == 2)//need rollback after upgrade
  801. {
  802. LOG4VTM(INFO, "upgrade restart 222");
  803. WriteRunInfoContent("222");
  804. //rollback
  805. EnterCriticalSectionRVC(g_cs);
  806. g_needToRollBack = 0;
  807. LeaveCriticalSectionRVC(g_cs);
  808. LOG4VTM(INFO, "healthmanager said to rollback");
  809. FrameworkRollBack();
  810. }
  811. else if (pInfo->dwParam1 == 3)//upgrade succeeded
  812. {
  813. LOG4VTM(INFO, "upgrade restart ok");
  814. WriteRunInfoContent("333");
  815. EnterCriticalSectionRVC(g_cs);
  816. g_needToRollBack = 0;
  817. LeaveCriticalSectionRVC(g_cs);
  818. }
  819. //runinfo.close();
  820. close(socket);
  821. }
  822. break;
  823. case GdOpFrameQuit:
  824. if (!g_bFrameOnline)
  825. {
  826. g_bFrameOnline = true;
  827. g_SpShellPID = GetSpshellProcID();
  828. LOG4VTM(INFO, "get spshell proc id" << g_SpShellPID);
  829. StartDoNetControlRVC();
  830. }
  831. EnterCriticalSectionRVC(g_cs);
  832. g_bFrameQuit = true;
  833. LeaveCriticalSectionRVC(g_cs);
  834. close(socket);
  835. break;
  836. default:
  837. break;
  838. }
  839. LOG4VTM(DEBUG, "quit of DataProcessLinux");
  840. }
  841. #else
  842. void DataProcess(LPPER_HANDLE_DATA pPerHandleData,LPPER_IO_OPERATION_DATA pPerIoData)
  843. {
  844. GuardianInfo* pInfo = (GuardianInfo*)pPerIoData->Buffer;
  845. switch(pInfo->eType)
  846. {
  847. case GdOpShakeHand:
  848. {
  849. if (!g_bFrameOnline)
  850. {
  851. g_bFrameOnline = true;
  852. StartDoNetControlRVC();
  853. }
  854. int rc,err;
  855. EnterCriticalSectionRVC(g_cs);
  856. g_bFrameQuit = false;
  857. g_dwTimeBegin = GetTickCount64();
  858. LeaveCriticalSectionRVC(g_cs);
  859. char* pBuf = new char[8];
  860. memset(pBuf,0,8);
  861. //get guardian state
  862. //ex:u(update),g(guardian),r(reboot),b(rollback)
  863. if (cnt%2 == 0)
  864. memcpy(pBuf,"g",1);
  865. else
  866. memcpy(pBuf,"u",1);
  867. cnt++;
  868. rc = send(pPerHandleData->Socket,pBuf,8,0);
  869. delete []pBuf;
  870. closesocket(pPerHandleData->Socket);
  871. }
  872. break;
  873. case GdOpUpdateTask:
  874. {
  875. if (!g_bFrameOnline)
  876. {
  877. g_bFrameOnline = true;
  878. StartDoNetControlRVC();
  879. }
  880. }
  881. break;
  882. case GdOpQueryInstall:
  883. {
  884. if (!g_bFrameOnline)
  885. {
  886. g_bFrameOnline = true;
  887. StartDoNetControlRVC();
  888. }
  889. int rc,err;
  890. char* pBuf = new char[8];
  891. memset(pBuf,0,8);
  892. if (cnt%2 == 0)
  893. memcpy(pBuf,"y",1);
  894. else
  895. memcpy(pBuf,"n",1);
  896. cnt++;
  897. rc = send(pPerHandleData->Socket,pBuf,8,0);
  898. delete []pBuf;
  899. closesocket(pPerHandleData->Socket);
  900. }
  901. break;
  902. case GdOpUpgradeRestart:
  903. {
  904. if (pInfo->dwParam1 == 6)//need Upgrade guardian !!!Only!!!
  905. {
  906. g_needUpgradeGuardianOnly = true;
  907. }
  908. if (pInfo->dwParam1 == 4)//just know framework is starting...
  909. {
  910. LOG4VTM(INFO, "framework is starting...");
  911. //oilyang@20211208 add the following if receive framework is starting ,reset g_dwUpgradeRestartTimeBegin
  912. //in order to skip the cost time of "kill spshell"
  913. g_dwUpgradeRestartTimeBegin = GetTickCount64();
  914. g_bFrameOnline = true;
  915. g_bAuthSuc = false;
  916. StartDoNetControlRVC();
  917. break;
  918. }
  919. if (pInfo->dwParam1 == 5)
  920. {
  921. LOG4VTM(INFO, "framework auth ok.");
  922. g_bInUpgrade = false;
  923. g_bAuthSuc = true;
  924. }
  925. if (!g_bFrameOnline)
  926. {
  927. g_bFrameOnline = true;
  928. StartDoNetControlRVC();
  929. }
  930. if (pInfo->dwParam1 == 1 || pInfo->dwParam1 == 3)
  931. g_dwTimeBegin = GetTickCount64();
  932. ServerReportEvent("upgrade restart");
  933. LOG4VTM(INFO, "upgrade restart " << pInfo->dwParam1);
  934. if (pInfo->dwParam1 == 1)//framework to restart after upgrade
  935. {
  936. g_bInUpgrade = true;
  937. WriteRunInfoContent("111");
  938. g_dwUpgradeRestartTimeBegin = GetTickCount64();
  939. }
  940. else if (pInfo->dwParam1 == 2)//need rollback after upgrade
  941. {
  942. LOG4VTM(INFO, "upgrade restart 222");
  943. WriteRunInfoContent("222");
  944. //rollback
  945. EnterCriticalSectionRVC(g_cs);
  946. g_needToRollBack = 0;
  947. LeaveCriticalSectionRVC(g_cs);
  948. LOG4VTM(INFO, "healthmanager said to rollback");
  949. FrameworkRollBack();
  950. }else if (pInfo->dwParam1 == 3)//upgrade succeeded
  951. {
  952. LOG4VTM(INFO, "upgrade restart ok");
  953. WriteRunInfoContent("333");
  954. EnterCriticalSectionRVC(g_cs);
  955. g_needToRollBack = 0;
  956. LeaveCriticalSectionRVC(g_cs);
  957. }
  958. //runinfo.close();
  959. closesocket(pPerHandleData->Socket);
  960. }
  961. break;
  962. case GdOpFrameQuit:
  963. if (!g_bFrameOnline)
  964. {
  965. g_bFrameOnline = true;
  966. StartDoNetControlRVC();
  967. }
  968. EnterCriticalSectionRVC(g_cs);
  969. g_bFrameQuit = true;
  970. LeaveCriticalSectionRVC(g_cs);
  971. closesocket(pPerHandleData->Socket);
  972. break;
  973. default:
  974. break;
  975. }
  976. }
  977. DWORD WINAPI ProcessIO(LPVOID lpParam)
  978. {
  979. HANDLE CompletionPort = (HANDLE)lpParam;
  980. DWORD BytesTransferred;
  981. LPPER_HANDLE_DATA PerHandleData;
  982. LPPER_IO_OPERATION_DATA PerIoData;
  983. while(true)
  984. {
  985. if(0 == GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED*)&PerIoData, INFINITE))
  986. {
  987. if( (GetLastError() == WAIT_TIMEOUT) || (GetLastError() == ERROR_NETNAME_DELETED) )
  988. {
  989. LOG4VTM(INFO, "closing socket(1) " << PerHandleData->Socket);
  990. closesocket(PerHandleData->Socket);
  991. delete PerIoData;
  992. delete PerHandleData;
  993. continue;
  994. }
  995. else
  996. {
  997. //OutErr("GetQueuedCompletionStatus failed!");
  998. }
  999. return 0;
  1000. }
  1001. // client quit
  1002. if(BytesTransferred == 0)
  1003. {
  1004. LOG4VTM(INFO, "closing socket(2) " <<PerHandleData->Socket);
  1005. closesocket(PerHandleData->Socket);
  1006. delete PerIoData;
  1007. delete PerHandleData;
  1008. continue;
  1009. }
  1010. // receiving data process
  1011. DataProcess(PerHandleData,PerIoData);
  1012. // socket WSARecv
  1013. DWORD Flags = 0;
  1014. DWORD dwRecv = 0;
  1015. ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA));
  1016. PerIoData->DataBuf.buf = PerIoData->Buffer;
  1017. PerIoData->DataBuf.len = DATA_BUFSIZE;
  1018. WSARecv(PerHandleData->Socket, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL);
  1019. }
  1020. return 0;
  1021. }
  1022. DWORD WINAPI DoWork(void* pData)
  1023. {
  1024. LOG4VTM(INFO, "to wait.");
  1025. HANDLE hTimer;
  1026. LARGE_INTEGER li;
  1027. hTimer = CreateWaitableTimer(NULL,FALSE,NULL);
  1028. const int nTimerUnitsPerSecond = 10000000;
  1029. li.QuadPart = -(1*60*nTimerUnitsPerSecond);//oiltmp 1 minute
  1030. SetWaitableTimer(hTimer,&li,2*60*1000,NULL,NULL,FALSE);
  1031. while(1)
  1032. {
  1033. WaitForSingleObject(hTimer,INFINITE);
  1034. EnterCriticalSectionRVC(g_cs);
  1035. if (!g_bFrameQuit)
  1036. {
  1037. ULONGLONG dwTmpBegin = g_dwTimeBegin;
  1038. ULONGLONG dwUpgradeTmpBegin = g_dwUpgradeRestartTimeBegin;
  1039. LeaveCriticalSectionRVC(g_cs);
  1040. ULONGLONG dwTimeEnd = GetTickCount64();
  1041. //oilyang@20190828 add
  1042. //升级重启后,在10分钟内,只要离最后一次交互时间大于MAX_WAIT_TIME_TO_RESTART_UPGRADE,重启框架
  1043. if (g_bInUpgrade && ((dwTimeEnd - dwTmpBegin) < MAX_WAIT_TIME_TO_RESTART)
  1044. && (!g_bAuthSuc && ((dwTimeEnd - dwUpgradeTmpBegin) > MAX_WAIT_TIME_TO_RESTART_UPGRADE)))
  1045. {
  1046. LOG4VTM(WARN, "**in upgrade restart**,to restart framework.");
  1047. FrameworkShutdown(true,true);
  1048. }
  1049. if ((dwTimeEnd-dwTmpBegin) > MAX_WAIT_TIME_TO_RESTART)
  1050. {
  1051. LOG4VTM(ERROR, "framework maybe down.");
  1052. string strRunInfo;
  1053. if (ReadRuninfoContent(strRunInfo))
  1054. {
  1055. LOG4VTM(INFO, "to check if need rollback.");
  1056. LOG4VTM(INFO, "runinfo:" << strRunInfo);
  1057. if (strRunInfo.compare("111") == 0 && IsStartTimeFileExist())
  1058. {
  1059. EnterCriticalSectionRVC(g_cs);
  1060. g_needToRollBack = 1;
  1061. LeaveCriticalSectionRVC(g_cs);
  1062. }
  1063. }
  1064. else
  1065. LOG4VTM(WARN, "read run info failed.");
  1066. if (g_needToRollBack)
  1067. {
  1068. LOG4VTM(INFO, "after upgrade,time elapse,but can't wait the shake hands,so rollback.");
  1069. FrameworkRollBack();
  1070. }
  1071. else
  1072. {
  1073. //framework is down,to restart it! oilyang 20150413
  1074. //oilyang@20211221 if Upgrade guardian !!!Only!!! ,just reset dwTmpBegin
  1075. if (!g_needUpgradeGuardianOnly)
  1076. FrameworkShutdown();
  1077. else
  1078. dwTmpBegin = GetTickCount64();
  1079. }
  1080. }
  1081. }
  1082. else
  1083. LeaveCriticalSectionRVC(g_cs);
  1084. }
  1085. EndThreadRVC();
  1086. return 0;
  1087. }
  1088. DWORD WINAPI DoNetControl(LPVOID pData)
  1089. {
  1090. ServerReportEvent("DoNetControl start");
  1091. HANDLE hSnapshot;
  1092. //find spshell.exe
  1093. hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1094. if (hSnapshot)
  1095. {
  1096. PROCESSENTRY32 pe;
  1097. pe.dwSize = sizeof(pe);
  1098. if (Process32First(hSnapshot, &pe))
  1099. {
  1100. do {
  1101. if (_stricmp(&pe.szExeFile[0], "spshell.exe") == 0)
  1102. {
  1103. //ServerReportEvent("find spshell.exe");
  1104. LOG4VTM(INFO, "find spshell.exe");
  1105. //DWORD dwExit = 0;
  1106. //do
  1107. //{
  1108. // GetExitCodeProcess(&pe.th32ProcessID,&dwExit);
  1109. // if (dwExit != STILL_ACTIVE)
  1110. // break;
  1111. //}while(1);
  1112. HANDLE hP = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID );
  1113. WaitForSingleObject(hP, INFINITE );
  1114. LOG4VTM(INFO, "spshell.exe quit");
  1115. break;
  1116. }
  1117. } while (Process32Next(hSnapshot, &pe));
  1118. }
  1119. CloseHandle(hSnapshot);
  1120. }
  1121. else
  1122. ServerReportEvent("create snapshot failed.");
  1123. EndThreadRVC();
  1124. return 0;
  1125. }
  1126. #endif //linux
  1127. int InitListenSocketRVC()
  1128. {
  1129. #ifdef linux
  1130. socklen_t clilen;
  1131. epfd = epoll_create(256);
  1132. struct sockaddr_in clientaddr;
  1133. struct sockaddr_in serveraddr;
  1134. g_sListen = socket(AF_INET, SOCK_STREAM, 0);
  1135. //setnonblocking(listenfd);
  1136. ev.data.fd = g_sListen;
  1137. ev.events = EPOLLIN | EPOLLET;
  1138. epoll_ctl(epfd, EPOLL_CTL_ADD, g_sListen, &ev);
  1139. memset(&serveraddr, 0, sizeof(serveraddr));
  1140. serveraddr.sin_family = AF_INET;
  1141. char* local_addr = "127.0.0.1";
  1142. inet_aton(local_addr, &(serveraddr.sin_addr));
  1143. serveraddr.sin_port = htons(default_port);
  1144. int tmpuse = 1;
  1145. if (setsockopt(g_sListen, SOL_SOCKET, SO_REUSEPORT, (char*)&tmpuse, sizeof(tmpuse)) < 0)
  1146. {
  1147. LOG4VTM(ERROR, "setsockopt failed. "<< errno);
  1148. LOG4VTM(ERROR, strerror(errno));
  1149. close(g_sListen);
  1150. return -1;
  1151. }
  1152. int ret = bind(g_sListen, (sockaddr*)& serveraddr, sizeof(serveraddr));
  1153. if (ret != 0)
  1154. {
  1155. LOG4VTM(ERROR, "bind failed: " << errno);
  1156. LOG4VTM(ERROR, strerror(errno));
  1157. close(g_sListen);
  1158. return -1;
  1159. }
  1160. ret= listen(g_sListen, LISTENQ);
  1161. if (ret != 0)
  1162. {
  1163. LOG4VTM(ERROR, "listen failed: " << errno);
  1164. LOG4VTM(ERROR, strerror(errno));
  1165. close(g_sListen);
  1166. return -1;
  1167. }
  1168. LOG4VTM(INFO, "(linux)listen ok: " << g_sListen);
  1169. cout << "listen on:" << g_sListen << endl;
  1170. return g_sListen;
  1171. #else
  1172. WSADATA wsaData;
  1173. int iResult;
  1174. struct addrinfo* result = NULL;
  1175. struct addrinfo hints;
  1176. int iSendResult;
  1177. char recvbuf[DEFAULT_BUFLEN];
  1178. int recvbuflen = DEFAULT_BUFLEN;
  1179. // Initialize Winsock
  1180. iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  1181. if (iResult != 0) {
  1182. LOG4VTM(ERROR, "WSAStartup failed with error:" << iResult);
  1183. return 1;
  1184. }
  1185. ZeroMemory(&hints, sizeof(hints));
  1186. hints.ai_family = AF_INET;
  1187. hints.ai_socktype = SOCK_STREAM;
  1188. hints.ai_protocol = IPPROTO_TCP;
  1189. hints.ai_flags = AI_PASSIVE;
  1190. // Resolve the server address and port
  1191. iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
  1192. if (iResult != 0) {
  1193. LOG4VTM(ERROR, "getaddrinfo failed with error:" << iResult);
  1194. WSACleanup();
  1195. return 1;
  1196. }
  1197. // get system info to create work thread
  1198. SYSTEM_INFO SystemInfo;
  1199. GetSystemInfo(&SystemInfo);
  1200. // Create a SOCKET for connecting to server
  1201. g_sListen = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  1202. if (g_sListen == INVALID_SOCKET) {
  1203. LOG4VTM(ERROR, "socket failed with error:" << WSAGetLastError());
  1204. freeaddrinfo(result);
  1205. WSACleanup();
  1206. return 1;
  1207. }
  1208. // Setup the TCP listening socket
  1209. struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*) result->ai_addr;
  1210. LOG4VTM(INFO, "ip:"<< inet_ntoa(sockaddr_ipv4->sin_addr));
  1211. iResult = bind(g_sListen, result->ai_addr, (int)result->ai_addrlen);
  1212. if (iResult == SOCKET_ERROR) {
  1213. LOG4VTM(ERROR, "bind failed with error:" << WSAGetLastError());
  1214. freeaddrinfo(result);
  1215. closesocket(g_sListen);
  1216. WSACleanup();
  1217. return 1;
  1218. }
  1219. freeaddrinfo(result);
  1220. LOG4VTM(INFO, "to listen.");
  1221. iResult = listen(g_sListen, SOMAXCONN);
  1222. if (iResult == SOCKET_ERROR) {
  1223. LOG4VTM(ERROR, "listen failed with error: " << WSAGetLastError());
  1224. closesocket(g_sListen);
  1225. WSACleanup();
  1226. return 1;
  1227. }
  1228. LOG4VTM(INFO, "listen ok.");
  1229. return g_sListen;
  1230. #endif //linux
  1231. }
  1232. void AcceptReqRVC()
  1233. {
  1234. #ifdef linux
  1235. StartDoWorkRVC();
  1236. LOG4VTM(DEBUG, "AcceptReqRVC:after StartDoWorkRVC");
  1237. int maxi, connfd, sockfd, nfds;
  1238. struct epoll_event events[20];
  1239. struct sockaddr_in clientaddr;
  1240. socklen_t clilen = sizeof(struct sockaddr);
  1241. ssize_t n;
  1242. maxi = 0;
  1243. char line[MAXLINE];
  1244. for (; ; ) {
  1245. //等待epoll事件的发生
  1246. nfds = epoll_wait(epfd, events, 20, 500);
  1247. //处理所发生的所有事件
  1248. for (int i = 0; i < nfds; ++i)
  1249. {
  1250. LOG4VTM(DEBUG, "nfds: " << nfds);
  1251. if (events[i].data.fd == g_sListen)//new connection
  1252. {
  1253. connfd = accept(g_sListen, (sockaddr*)& clientaddr, &clilen);
  1254. if (connfd < 0) {
  1255. LOG4VTM(ERROR, "connfd<0");
  1256. perror("connfd<0");
  1257. exit(1);
  1258. }
  1259. //setnonblocking(connfd);
  1260. char* str = inet_ntoa(clientaddr.sin_addr);
  1261. LOG4VTM(DEBUG, "accapt a connection from " << str);
  1262. ev.data.fd = connfd;
  1263. ev.events = EPOLLIN | EPOLLET;
  1264. //ev.events=EPOLLIN;
  1265. epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
  1266. }
  1267. else if (events[i].events & EPOLLIN)
  1268. {
  1269. LOG4VTM(DEBUG, "EPOLLIN,i:" << i << ",sock:" << events[i].data.fd);
  1270. if ((sockfd = events[i].data.fd) < 0)
  1271. continue;
  1272. if ((n = read(sockfd, line, MAXLINE)) < 0) {
  1273. if (errno == ECONNRESET) {
  1274. close(sockfd);
  1275. events[i].data.fd = -1;
  1276. }
  1277. else
  1278. LOG4VTM(ERROR, "readline error: " << strerror(errno));
  1279. }
  1280. else if (n == 0) {
  1281. close(sockfd);
  1282. events[i].data.fd = -1;
  1283. }
  1284. DataProcessLinux(sockfd,line);
  1285. line[n] = '\0';
  1286. ev.data.fd = sockfd;
  1287. ev.events = EPOLLOUT | EPOLLET;
  1288. epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
  1289. LOG4VTM(DEBUG, "out DataProcessLinux");
  1290. }
  1291. else if (events[i].events & EPOLLOUT)
  1292. {
  1293. LOG4VTM(DEBUG, "epoll out");
  1294. sockfd = events[i].data.fd;
  1295. write(sockfd, line, n);
  1296. ev.data.fd = sockfd;
  1297. ev.events = EPOLLIN | EPOLLET;
  1298. epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
  1299. }
  1300. }
  1301. }
  1302. #else
  1303. HANDLE hCompletionPort;
  1304. hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
  1305. // get system info to create work thread
  1306. SYSTEM_INFO SystemInfo;
  1307. GetSystemInfo(&SystemInfo);
  1308. for (int i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
  1309. {
  1310. HANDLE hProcessIO = CreateThread(NULL, 0, ProcessIO, hCompletionPort, 0, NULL);
  1311. if (hProcessIO)
  1312. CloseHandle(hProcessIO);
  1313. }
  1314. //waiting thread
  1315. StartDoWorkRVC();
  1316. SOCKET sClient;
  1317. LPPER_HANDLE_DATA PerHandleData;
  1318. LPPER_IO_OPERATION_DATA PerIoData;
  1319. while (true)
  1320. {
  1321. //sClient = WSAAccept(sListen, NULL, NULL, NULL, 0);
  1322. sClient = accept(g_sListen, NULL, NULL);
  1323. //cout << "Socket " << sClient << "connect" << endl;
  1324. PerHandleData = new PER_HANDLE_DATA();
  1325. PerHandleData->Socket = sClient;
  1326. // client completion port
  1327. CreateIoCompletionPort((HANDLE)sClient, hCompletionPort, (DWORD)PerHandleData, 0);
  1328. //
  1329. PerIoData = new PER_IO_OPERATION_DATA();
  1330. ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA));
  1331. PerIoData->DataBuf.buf = PerIoData->Buffer;
  1332. PerIoData->DataBuf.len = DATA_BUFSIZE;
  1333. // WSARecv
  1334. DWORD Flags = 0;
  1335. DWORD dwRecv = 0;
  1336. WSARecv(sClient, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL);
  1337. LOG4VTM(DEBUG, "hold");
  1338. }
  1339. DWORD dwByteTrans;
  1340. PostQueuedCompletionStatus(hCompletionPort, dwByteTrans, 0, 0);
  1341. closesocket(g_sListen);
  1342. #endif //linux
  1343. }
  1344. #if linux
  1345. static void sig_handle(int signo)
  1346. {
  1347. switch (signo) {
  1348. case SIGSEGV:
  1349. {
  1350. LOG4VTM(INFO, "=========>>> capture signal SIGSEGV <<<=========");
  1351. break;
  1352. }
  1353. case SIGTERM:
  1354. LOG4VTM(INFO, "=========>>> capture signal SIGTERM <<<=========");
  1355. break;
  1356. case SIGCHLD:
  1357. {
  1358. LOG4VTM(INFO, "=========>>> capture signal SIGCHLD <<<=========");
  1359. if (signal(SIGCHLD, sig_handle) == SIG_ERR)
  1360. LOG4VTM(ERROR, "signal error.");
  1361. int status;
  1362. pid_t pid;
  1363. while ((pid = waitpid(0, &status, WNOHANG)) > 0) {
  1364. char szMsg[256] = { '\0' };
  1365. bool excep(false);
  1366. if (WIFEXITED(status)) {
  1367. sprintf(szMsg, "child process %d terminated normal with exit code: %d", pid, WEXITSTATUS(status));
  1368. } else {
  1369. const int signum = WTERMSIG(status);
  1370. sprintf(szMsg, "child process %d has been terminated unexpectly by signal %d", pid, signum);
  1371. //if(signum != SIGKILL)
  1372. excep = true;
  1373. }
  1374. LOG4VTM(INFO, szMsg);
  1375. if (g_SpShellPID != 0 && g_SpShellPID == pid) {
  1376. LOG4VTM(INFO, "Specified spshell process has exited!");
  1377. g_SpShellPID = 0;
  1378. if (excep) {
  1379. LOG4VTM(INFO, "Confirm other relate process has been terminated.");
  1380. int count = 60;
  1381. alive_process_info processes[60];
  1382. memset(processes, 0, sizeof(processes));
  1383. if (!osutil_detect_unique_app(relate_processes_ex, array_size(relate_processes_ex), &count, processes)) {
  1384. bool spshell_exist(false);
  1385. for (int i = 0; i < count; ++i) {
  1386. if (strcmp(processes[i].name, spshell_execute_name) == 0) {
  1387. spshell_exist = true;
  1388. break;
  1389. }
  1390. }
  1391. for (int i = 0; !spshell_exist && i < count; ++i) {
  1392. kill(processes[i].pid, SIGKILL);
  1393. LOG4VTM(INFO, "kill " << processes[i].name << ", pid: " << processes[i].pid << ", err: " <<errno);
  1394. }
  1395. }
  1396. }
  1397. }
  1398. }
  1399. break;
  1400. }
  1401. default:
  1402. char szMsg[256] = { '\0' };
  1403. sprintf(szMsg, "=========>>> capture signal %d <<<=========", signo);
  1404. LOG4VTM(INFO, szMsg);
  1405. break;
  1406. }
  1407. return;
  1408. }
  1409. #endif
  1410. int main(int argc, char* argv[])
  1411. {
  1412. //attach file descriptors 0,1,2 to /dev/null(for deamon app)
  1413. std::string terminalno;
  1414. int fd0, fd1, fd2;
  1415. g_bFrameOnline = true;
  1416. //MessageBox(NULL, NULL, NULL, 0);
  1417. if (argc > 1)
  1418. terminalno = argv[1];
  1419. #ifdef linux
  1420. fd0 = open("/dev/null", O_RDWR);
  1421. fd1 = dup(0);
  1422. fd2 = dup(0);
  1423. pthread_mutex_init(&g_cs_event,NULL);
  1424. pthread_mutex_init(&g_cs_log,NULL);
  1425. pthread_mutex_init(&g_cs,NULL);
  1426. #else
  1427. InitializeCriticalSectionAndSpinCount(&g_cs_event, 100);
  1428. InitializeCriticalSectionAndSpinCount(&g_cs_log, 100);
  1429. InitializeCriticalSectionAndSpinCount(&g_cs, 100);
  1430. ZeroMemory(currDirBuf, sizeof(currDirBuf));
  1431. ZeroMemory(chDisk, sizeof(chDisk));
  1432. GetCurrentDirectory(256, currDirBuf);
  1433. chDisk[0] = currDirBuf[0];
  1434. #endif
  1435. cmb::log_init_config config;
  1436. config.dev_name = "guardian";
  1437. config.terminalno = terminalno;
  1438. ///*TODO: 依赖上层提供环境变量来控制路径和开关,可以考虑厂商的方式 (80374374@1/4/2024)*/
  1439. #if defined(_MSC_VER)
  1440. config.log_dir = ("C:\\rvc\\dbg\\");
  1441. #else
  1442. config.log_dir = ("/opt/rvc/dbg/");
  1443. #endif //_MSC_VER
  1444. std::string str;
  1445. cmb::log4rvcother::init(config, str);
  1446. g_dwTimeBegin = GetTickCount64();
  1447. int i=1000;
  1448. LOG4VTM(INFO, "guardian version: " << GUARDIAN_VERSION_STR);
  1449. #if linux
  1450. g_SpShellPID = GetSpshellProcID();
  1451. LOG4VTM(INFO, ("get spshell proc id: ") << g_SpShellPID);
  1452. if (signal(SIGCHLD, sig_handle) == SIG_ERR) {
  1453. LOG4VTM(WARN, ("register for SIGCHLD failed: ") << errno);
  1454. } else {
  1455. LOG4VTM(DEBUG, ("register for SIGCHLD succ."));
  1456. }
  1457. #endif
  1458. StartDoNetControlRVC();
  1459. InitListenSocketRVC();
  1460. AcceptReqRVC();
  1461. }