Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

842 lines
24 KiB

  1. //////////////////////////////////////////////////////////////////////
  2. // File: StressInstance.cpp
  3. //
  4. // Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // Purpose:
  7. // StressInstance.cpp: interface for the StressInstance class.
  8. // This class is used spawn and monitor instances of the stressEXE app
  9. //
  10. // History:
  11. // 02/15/01 DennisCh Created
  12. //
  13. //////////////////////////////////////////////////////////////////////
  14. //////////////////////////////////////////////////////////////////////
  15. //
  16. // Includes
  17. //
  18. //////////////////////////////////////////////////////////////////////
  19. //
  20. // Win32 headers
  21. //
  22. //
  23. // Project headers
  24. //
  25. #include "StressInstance.h"
  26. #include "ServerCommands.h"
  27. #include "NetworkTools.h"
  28. #include "MemStats.h"
  29. #include "debugger.h"
  30. //////////////////////////////////////////////////////////////////////
  31. //
  32. // Globals and statics
  33. //
  34. //////////////////////////////////////////////////////////////////////
  35. extern ServerCommands g_objServerCommands; // Declared in WinHttpStressScheduler.cpp
  36. extern HWND g_hWnd; // Declared in WinHttpStressScheduler.cpp
  37. StressInstance *g_hThis; // the current StressInstance object. Used only in (friend) StressExe_TimerProc.
  38. UINT_PTR g_uiStressExeTimerID; // ID for the timer that monitors the stressExe when it's spawned
  39. // Forward function definitions
  40. VOID
  41. CALLBACK
  42. StressExe_TimerProc(
  43. HWND hwnd, // [IN] handle to window
  44. UINT uMsg, // [IN] WM_TIMER message
  45. UINT_PTR idEvent, // [IN] timer identifier
  46. DWORD dwTime // [IN] current system time
  47. );
  48. DWORD
  49. DebuggerCallbackProc(
  50. DWORD dwFlags,
  51. LPVOID lpIn,
  52. LPTSTR lpszFutureString,
  53. LPVOID lpFuturePointer
  54. );
  55. //////////////////////////////////////////////////////////////////////
  56. // Construction/Destruction
  57. //////////////////////////////////////////////////////////////////////
  58. StressInstance::StressInstance()
  59. {
  60. m_szStressExe_URL = new TCHAR[MAX_STRESS_URL];
  61. m_szStressExe_PDB_URL = new TCHAR[MAX_STRESS_URL];
  62. m_szStressExe_SYM_URL = new TCHAR[MAX_STRESS_URL];
  63. m_szStressExe_FilePath = new TCHAR[MAX_STRESS_URL];
  64. m_szStressExe_FileName = new TCHAR[MAX_STRESS_URL];
  65. m_szStressExe_FilePathAndName = new TCHAR[MAX_STRESS_URL];
  66. m_szStressExe_PageHeapCommandLine = new TCHAR[MAX_PATH];
  67. m_szStressExe_UMDHCommandLine = new TCHAR[MAX_PATH];
  68. m_szStressExe_MemDumpPath = new TCHAR[MAX_PATH];
  69. ZeroMemory(m_szStressExe_URL, MAX_STRESS_URL);
  70. ZeroMemory(m_szStressExe_PDB_URL, MAX_STRESS_URL);
  71. ZeroMemory(m_szStressExe_SYM_URL, MAX_STRESS_URL);
  72. ZeroMemory(m_szStressExe_FilePath, MAX_STRESS_URL);
  73. ZeroMemory(m_szStressExe_FileName, MAX_STRESS_URL);
  74. ZeroMemory(m_szStressExe_FilePathAndName, MAX_STRESS_URL);
  75. ZeroMemory(m_szStressExe_PageHeapCommandLine, MAX_PATH);
  76. ZeroMemory(m_szStressExe_UMDHCommandLine, MAX_PATH);
  77. ZeroMemory(m_szStressExe_MemDumpPath, MAX_PATH);
  78. ZeroMemory(&m_piStressExeProcess, sizeof(PROCESS_INFORMATION));
  79. m_hStressExe_ProcessExitEvent = NULL;
  80. g_uiStressExeTimerID = 0;
  81. m_objDebugger = NULL;
  82. g_hThis = this;
  83. }
  84. StressInstance::~StressInstance()
  85. {
  86. // End any running tests
  87. if (IsRunning(STRESSINSTANCE_STRESS_EXE_CLOSE_TIMEOUT))
  88. StressInstance::End();
  89. delete [] m_szStressExe_URL;
  90. delete [] m_szStressExe_PDB_URL;
  91. delete [] m_szStressExe_SYM_URL;
  92. delete [] m_szStressExe_FilePath;
  93. delete [] m_szStressExe_FileName;
  94. delete [] m_szStressExe_FilePathAndName;
  95. delete [] m_szStressExe_PageHeapCommandLine;
  96. delete [] m_szStressExe_UMDHCommandLine;
  97. delete [] m_szStressExe_MemDumpPath;
  98. m_szStressExe_URL = NULL;
  99. m_szStressExe_PDB_URL = NULL;
  100. m_szStressExe_SYM_URL = NULL;
  101. m_szStressExe_FilePath = NULL;
  102. m_szStressExe_FileName = NULL;
  103. m_szStressExe_FilePathAndName = NULL;
  104. m_szStressExe_PageHeapCommandLine = NULL;
  105. m_szStressExe_UMDHCommandLine = NULL;
  106. m_szStressExe_MemDumpPath = NULL;
  107. // close stressExe process handles
  108. if (m_piStressExeProcess.hThread)
  109. CloseHandle(m_piStressExeProcess.hThread);
  110. if (m_piStressExeProcess.hProcess)
  111. CloseHandle(m_piStressExeProcess.hProcess);
  112. if (m_hStressExe_ProcessExitEvent)
  113. CloseHandle(m_hStressExe_ProcessExitEvent);
  114. m_piStressExeProcess.hThread = NULL;
  115. m_piStressExeProcess.hProcess = NULL;
  116. m_hStressExe_ProcessExitEvent = NULL;
  117. // free debugger object
  118. if (m_objDebugger)
  119. {
  120. delete m_objDebugger;
  121. m_objDebugger = NULL;
  122. }
  123. g_hThis = NULL;
  124. }
  125. ////////////////////////////////////////////////////////////
  126. // Function: StressInstance::Begin()
  127. //
  128. // Purpose:
  129. // This method begins stress by downloading the stress EXE from
  130. // m_szStressExe_URL and starts it in CDB.
  131. //
  132. ////////////////////////////////////////////////////////////
  133. BOOL
  134. StressInstance::Begin()
  135. {
  136. BOOL bResult = TRUE;
  137. LPTSTR szCommandLine = new TCHAR[MAX_STRESS_URL*4];
  138. LPTSTR szFileNameAndPath = new TCHAR[MAX_STRESS_URL*2];
  139. DWORD dwCommandLineSize = MAX_STRESS_URL*4;
  140. DWORD dwFileNameAndPathSize = MAX_STRESS_URL*2;
  141. LPSTARTUPINFO pStartUpInfo = new STARTUPINFO;
  142. // don't start if stress is already running or we don't have a FileName or Path.
  143. if (IsRunning(5000) ||
  144. 0 >= _tcslen(m_szStressExe_FilePath) ||
  145. 0 >= _tcslen(m_szStressExe_FileName))
  146. goto Exit;
  147. // ********************************
  148. // ********************************
  149. // ** Download the stressExe and symbols.
  150. // **
  151. if (!DownloadStressExe())
  152. {
  153. bResult = FALSE;
  154. goto Exit;
  155. }
  156. // ********************************
  157. // ********************************
  158. // ** Enable pageheap if needed
  159. // **
  160. if (0 < _tcsclen(m_szStressExe_PageHeapCommandLine))
  161. {
  162. if (!NetworkTools__PageHeap(TRUE, m_szStressExe_FileName, m_szStressExe_PageHeapCommandLine))
  163. {
  164. NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "Pageheap failed when trying to enable.", NULL, Get_ID());
  165. bResult = FALSE;
  166. // goto Exit; don't need to exit when pageheap fails
  167. }
  168. else
  169. NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "Pageheap successfully enabled.", NULL, Get_ID());
  170. }
  171. // ********************************
  172. // ********************************
  173. // ** Create the stressExe process
  174. // **
  175. // build Remote/CDB/stressExe path
  176. ZeroMemory(szCommandLine, dwCommandLineSize);
  177. _stprintf(szCommandLine, STRESSINSTANCE_DEBUG_COMMANDLINE, m_szStressExe_FilePathAndName);
  178. // startupInfo
  179. ZeroMemory(pStartUpInfo, sizeof(STARTUPINFO));
  180. pStartUpInfo->cb = sizeof(STARTUPINFO);
  181. pStartUpInfo->dwFillAttribute = FOREGROUND_RED| BACKGROUND_RED| BACKGROUND_GREEN| BACKGROUND_BLUE; // red text on white background
  182. pStartUpInfo->dwFlags = STARTF_USESHOWWINDOW;
  183. pStartUpInfo->wShowWindow = SW_MINIMIZE;
  184. // Create the stressExe process
  185. bResult =
  186. CreateProcess(
  187. NULL,
  188. m_szStressExe_FilePathAndName,
  189. NULL,
  190. NULL,
  191. TRUE,
  192. CREATE_NEW_CONSOLE | CREATE_SEPARATE_WOW_VDM | NORMAL_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP | CREATE_SUSPENDED,
  193. NULL,
  194. NULL,
  195. pStartUpInfo,
  196. &m_piStressExeProcess);
  197. if (!bResult)
  198. {
  199. // stressExe failed to start
  200. goto Exit;
  201. }
  202. // ********************************
  203. // ********************************
  204. // ** Attach debugger to the process only if there isn't one
  205. // **
  206. // remove debugger if there is one
  207. if (m_objDebugger)
  208. {
  209. delete m_objDebugger;
  210. m_objDebugger = NULL;
  211. }
  212. // attach new debugger
  213. Sleep(2000);
  214. m_objDebugger = new Debugger(m_piStressExeProcess.dwProcessId, DebuggerCallbackProc);
  215. m_objDebugger->Go();
  216. ResumeThread(m_piStressExeProcess.hThread);
  217. // ********************************
  218. // ********************************
  219. // ** Initialize dynamically named event objects.
  220. // ** Set object access to ALL.
  221. // **
  222. // Create event object that'll be inherited by the stressExe process.
  223. // StressScheduler will signal when it's time to close stressExe.
  224. SECURITY_ATTRIBUTES securityAttributes;
  225. PSECURITY_DESCRIPTOR pSD;
  226. pSD = new SECURITY_DESCRIPTOR;
  227. // Set a NULL security descriptor. This gives full access to handles when inherited
  228. InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
  229. SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE);
  230. securityAttributes.bInheritHandle = TRUE;
  231. securityAttributes.lpSecurityDescriptor = pSD;
  232. securityAttributes.nLength = sizeof(securityAttributes);
  233. // The named event object names have the PID of the process appended to the end of the constants
  234. // These strings are also created in the stressExe dynamically.
  235. LPTSTR szExitProcessName;
  236. LPTSTR szPID;
  237. szExitProcessName = new TCHAR[MAX_PATH];
  238. szPID = new TCHAR[16];
  239. // Get the processID string
  240. _itot(m_piStressExeProcess.dwProcessId, szPID, 10);
  241. // build ExitProcess event object name
  242. _tcscpy(szExitProcessName, STRESSINSTANCE_STRESS_EXE_EVENT_EXITPROCESS);
  243. _tcscat(szExitProcessName, szPID);
  244. if (m_hStressExe_ProcessExitEvent)
  245. CloseHandle(m_hStressExe_ProcessExitEvent);
  246. // this event is sent by us to stressExe when we want it to exit
  247. // Signaled = tell stressExe to exit; Not-Signaled = stressExe can continue running
  248. m_hStressExe_ProcessExitEvent = CreateEvent(
  249. &securityAttributes,
  250. FALSE, // manual reset
  251. FALSE,
  252. szExitProcessName);
  253. delete [] szExitProcessName;
  254. delete [] szPID;
  255. delete [] pSD;
  256. // ********************************
  257. // ********************************
  258. // ** Begin the stressExe memory monitoring timerproc
  259. // **
  260. if (g_uiStressExeTimerID)
  261. {
  262. // there shouldn't be a timer already going. If so, nuke it.
  263. KillTimer(NULL, g_uiStressExeTimerID);
  264. g_uiStressExeTimerID = 0;
  265. }
  266. // create a new timer object
  267. g_uiStressExeTimerID =
  268. SetTimer(
  269. NULL,
  270. 0,
  271. STRESSINSTANCE_MONITOR_EXE_TIME,
  272. (TIMERPROC) StressExe_TimerProc);
  273. // Notify the Command Server that stress has started
  274. NetworkTools__SendLog(FIELDNAME__LOGTYPE_BEGIN, "This stressInstance has begun.", NULL, Get_ID());
  275. Exit:
  276. delete [] szCommandLine;
  277. delete [] szFileNameAndPath;
  278. delete [] pStartUpInfo;
  279. return bResult;
  280. }
  281. ////////////////////////////////////////////////////////////
  282. // Function: StressInstance::End()
  283. //
  284. // Purpose:
  285. // This method ends stress by sending a message
  286. //
  287. ////////////////////////////////////////////////////////////
  288. VOID
  289. StressInstance::End()
  290. {
  291. // ******************************
  292. // ******************************
  293. // ** End the stressExe monitoring timerproc
  294. if (g_uiStressExeTimerID)
  295. KillTimer(NULL, g_uiStressExeTimerID);
  296. // ******************************
  297. // ******************************
  298. // ** Tell stressExe to shut down.
  299. SetEvent(m_hStressExe_ProcessExitEvent);
  300. // give time for the stressExe to exit
  301. Sleep(2000);
  302. // close stressExe process handles
  303. if (m_piStressExeProcess.hThread)
  304. CloseHandle(m_piStressExeProcess.hThread);
  305. if (m_piStressExeProcess.hProcess)
  306. CloseHandle(m_piStressExeProcess.hProcess);
  307. if (m_hStressExe_ProcessExitEvent)
  308. CloseHandle(m_hStressExe_ProcessExitEvent);
  309. m_piStressExeProcess.hThread = NULL;
  310. m_piStressExeProcess.hProcess = NULL;
  311. m_hStressExe_ProcessExitEvent = NULL;
  312. // stop stressExe if it's still running
  313. if (IsRunning(STRESSINSTANCE_STRESS_EXE_CLOSE_TIMEOUT))
  314. {
  315. // stressExe failed to signal that it exited.
  316. // Bad stressExe, terminate the process.
  317. BOOL temp = TerminateProcess(m_piStressExeProcess.hProcess, 0);
  318. }
  319. // ********************************
  320. // ********************************
  321. // ** Detach the debugger object
  322. // **
  323. // detaching the debugger will (read: should) stop the stressExe
  324. if (m_objDebugger)
  325. {
  326. // ********************************
  327. // ********************************
  328. // ** Disable pageheap if needed
  329. // **
  330. NetworkTools__PageHeap(FALSE, m_szStressExe_FileName, NULL);
  331. // let the Command Server know that stressExe has ended
  332. // we send the message here because ServerCommands.cpp calls this too - even when
  333. // there isn't a running test case.
  334. // When the debugger object is valid, then we send the message - because it ensures that Begin() was called.
  335. NetworkTools__SendLog(FIELDNAME__LOGTYPE_END, "This stressInstance has ended.", NULL, Get_ID());
  336. delete m_objDebugger;
  337. m_objDebugger = NULL;
  338. }
  339. ZeroMemory(&m_piStressExeProcess, sizeof(PROCESS_INFORMATION));
  340. }
  341. ////////////////////////////////////////////////////////////
  342. // Function: StressInstance::Get_StressExeID()
  343. //
  344. // Purpose:
  345. // Returns the stress instance's ID receivedfrom the server
  346. //
  347. ////////////////////////////////////////////////////////////
  348. DWORD
  349. StressInstance::Get_ID()
  350. {
  351. return m_dwStressExe_ID;
  352. }
  353. ////////////////////////////////////////////////////////////
  354. // Function: StressInstance::Get_StressExeMemoryDumpPath()
  355. //
  356. // Purpose:
  357. // Sets the URL of the memory dump path
  358. //
  359. ////////////////////////////////////////////////////////////
  360. LPTSTR
  361. StressInstance::Get_StressExeMemoryDumpPath()
  362. {
  363. return m_szStressExe_MemDumpPath;
  364. }
  365. ////////////////////////////////////////////////////////////
  366. // Function: StressInstance::Set_StressExeMemoryDumpPath()
  367. //
  368. // Purpose:
  369. // Sets the URL of the memory dump path
  370. //
  371. ////////////////////////////////////////////////////////////
  372. VOID
  373. StressInstance::Set_StressExeMemoryDumpPath(
  374. LPTSTR szPath
  375. )
  376. {
  377. _tcsncpy(m_szStressExe_MemDumpPath, szPath, MAX_PATH);
  378. }
  379. ////////////////////////////////////////////////////////////
  380. // Function: StressInstance::Set_StressExeURL(LPTSTR)
  381. //
  382. // Purpose:
  383. // Sets the URL to download the stress EXE for this object.
  384. //
  385. ////////////////////////////////////////////////////////////
  386. VOID
  387. StressInstance::Set_StressExeURL(
  388. LPTSTR szBuffer // [IN] Buffer containing the URL to download the stressExe app
  389. )
  390. {
  391. if (!szBuffer || (0 >= _tcslen(szBuffer)))
  392. return;
  393. _tcscpy(m_szStressExe_URL, szBuffer);
  394. // Set the stressExe's filename
  395. NetworkTools__GetFileNameFromURL(m_szStressExe_URL, m_szStressExe_FileName, MAX_STRESS_URL);
  396. // Set the stressExe's default path to download to with trailing slash
  397. GetCurrentDirectory(MAX_STRESS_URL, m_szStressExe_FilePath);
  398. _tcscat(m_szStressExe_FilePath, _T("\\") STRESSINSTANCE_STRESS_EXE_DOWNLOAD_DIR _T("\\"));
  399. // Set the full stressExe path + exe
  400. _tcscpy(m_szStressExe_FilePathAndName, m_szStressExe_FilePath);
  401. _tcscat(m_szStressExe_FilePathAndName, m_szStressExe_FileName);
  402. }
  403. ////////////////////////////////////////////////////////////
  404. // Function: StressInstance::Set_StressExePdbURL(LPTSTR)
  405. //
  406. // Purpose:
  407. // Sets the URL to download the stress EXE's PDB file.
  408. //
  409. ////////////////////////////////////////////////////////////
  410. VOID
  411. StressInstance::Set_StressExePdbURL(
  412. LPTSTR szBuffer // [IN] Buffer containing the URL
  413. )
  414. {
  415. if (!szBuffer || (0 >= _tcslen(szBuffer)))
  416. return;
  417. _tcscpy(m_szStressExe_PDB_URL, szBuffer);
  418. }
  419. ////////////////////////////////////////////////////////////
  420. // Function: StressInstance::Set_StressExeSymURL(LPTSTR)
  421. //
  422. // Purpose:
  423. // Sets the URL to download the stress EXE's SYM file.
  424. //
  425. ////////////////////////////////////////////////////////////
  426. VOID
  427. StressInstance::Set_StressExeSymURL(
  428. LPTSTR szBuffer // [IN] Buffer containing the URL
  429. )
  430. {
  431. if (!szBuffer || (0 >= _tcslen(szBuffer)))
  432. return;
  433. _tcscpy(m_szStressExe_SYM_URL, szBuffer);
  434. }
  435. ////////////////////////////////////////////////////////////
  436. // Function: StressInstance::Set_StressExeID(DWORD)
  437. //
  438. // Purpose:
  439. // Sets the URL to download the stress EXE for this object.
  440. //
  441. ////////////////////////////////////////////////////////////
  442. VOID
  443. StressInstance::Set_StressExeID(
  444. DWORD dwID // [IN] ID from the stressAdmin DB uniquely identifying this stress EXE.
  445. )
  446. {
  447. m_dwStressExe_ID = dwID;
  448. }
  449. ////////////////////////////////////////////////////////////
  450. // Function: StressInstance::Set_PageHeapCommands(LPCTSTR)
  451. //
  452. // Purpose:
  453. // Sets the pageheap command line.
  454. //
  455. ////////////////////////////////////////////////////////////
  456. VOID
  457. StressInstance::Set_PageHeapCommands(
  458. LPCTSTR szCommandLine // [IN] Extra command line params for pageheap.
  459. )
  460. {
  461. ZeroMemory(m_szStressExe_PageHeapCommandLine, MAX_PATH);
  462. _tcsncpy(m_szStressExe_PageHeapCommandLine, szCommandLine, MAX_PATH-1);
  463. }
  464. ////////////////////////////////////////////////////////////
  465. // Function: StressInstance::Set_UMDHCommands(LPCTSTR)
  466. //
  467. // Purpose:
  468. // Sets the UMDH command line.
  469. //
  470. ////////////////////////////////////////////////////////////
  471. VOID
  472. StressInstance::Set_UMDHCommands(
  473. LPCTSTR szCommandLine // [IN] Extra command line params for UMDH.
  474. )
  475. {
  476. ZeroMemory(m_szStressExe_UMDHCommandLine, MAX_PATH);
  477. _tcsncpy(m_szStressExe_UMDHCommandLine, szCommandLine, MAX_PATH-1);
  478. }
  479. ////////////////////////////////////////////////////////////
  480. // Function: StressInstance::DownloadStressExe()
  481. //
  482. // Purpose:
  483. // Downloads the stressExe app to the local machine.
  484. // We create a directory of the stress exe name. For example,
  485. // "http://hairball/files/stress1.exe" will be put in "stress1\stress1.exe"
  486. // on the local machine. If the file is already there, it'll try to overwrite it.
  487. //
  488. ////////////////////////////////////////////////////////////
  489. BOOL
  490. StressInstance::DownloadStressExe()
  491. {
  492. BOOL bResult = TRUE;
  493. LPTSTR szFileName = new TCHAR[MAX_PATH];
  494. // Download the stressExe file
  495. if (NetworkTools__URLDownloadToFile(m_szStressExe_URL, STRESSINSTANCE_STRESS_EXE_DOWNLOAD_DIR, m_szStressExe_FileName))
  496. NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "stress EXE file downloaded successfully.", NULL, Get_ID());
  497. else
  498. {
  499. NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "stress EXE file not downloaded.", NULL, Get_ID());
  500. bResult = FALSE;
  501. }
  502. // Download PDB symbol file if there is one
  503. if (NetworkTools__GetFileNameFromURL(m_szStressExe_PDB_URL, szFileName, MAX_PATH))
  504. {
  505. NetworkTools__URLDownloadToFile(m_szStressExe_PDB_URL, STRESSINSTANCE_STRESS_EXE_DOWNLOAD_DIR, szFileName);
  506. NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "stress PDB file downloaded successfully.", NULL, Get_ID());
  507. }
  508. else
  509. NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "stress PDB file not downloaded.", NULL, Get_ID());
  510. // Download SYM symbol file if there is one
  511. if (NetworkTools__GetFileNameFromURL(m_szStressExe_SYM_URL, szFileName, MAX_PATH))
  512. {
  513. NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "stress SYM file downloaded successfully.", NULL, Get_ID());
  514. NetworkTools__URLDownloadToFile(m_szStressExe_SYM_URL, STRESSINSTANCE_STRESS_EXE_DOWNLOAD_DIR, szFileName);
  515. }
  516. else
  517. NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "streses SYM file not downloaded.", NULL, Get_ID());
  518. delete [] szFileName;
  519. return bResult;
  520. }
  521. ////////////////////////////////////////////////////////////
  522. // Function: StressInstance::IsRunning()
  523. //
  524. // Purpose:
  525. // Returns TRUE if this stressinstance is running. FALSE if not.
  526. //
  527. ////////////////////////////////////////////////////////////
  528. BOOL StressInstance::IsRunning(DWORD dwTimeOut)
  529. {
  530. BOOL bResult = FALSE;
  531. HANDLE hStressExe = NULL;
  532. hStressExe = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_piStressExeProcess.dwProcessId);
  533. if (!hStressExe)
  534. bResult = FALSE;
  535. else
  536. {
  537. bResult = TRUE;
  538. CloseHandle(hStressExe);
  539. }
  540. return bResult;
  541. }
  542. ////////////////////////////////////////////////////////////
  543. // Function: StressExe_TimerProc(HWND, UINT, UINT_PTR, DWORD)
  544. //
  545. // Purpose:
  546. // When this is called, we will check on the status of the
  547. // stressExe process send the command server it's memory info
  548. //
  549. ////////////////////////////////////////////////////////////
  550. VOID
  551. CALLBACK
  552. StressExe_TimerProc(
  553. HWND hwnd, // [IN] handle to window - should be NULL since we didn't specify one
  554. UINT uMsg, // [IN] WM_TIMER message
  555. UINT_PTR idEvent, // [IN] timer identifier
  556. DWORD dwTime // [IN] current system time
  557. )
  558. {
  559. // build directory to copy dump file
  560. LPSTR szExeName = new CHAR[MAX_STRESS_URL];
  561. if (!g_hThis)
  562. goto Exit;
  563. // ***********************************
  564. // ***********************************
  565. // ** Check that the stressExe is still running. If it isn't end this instance.
  566. // **
  567. if (!g_hThis->IsRunning(STRESSINSTANCE_STRESS_EXE_CLOSE_TIMEOUT))
  568. {
  569. NetworkTools__SendLog(FIELDNAME__LOGTYPE_INFORMATION, "This stress instance has exited prematurely.", NULL, g_hThis->Get_ID());
  570. g_hThis->End();
  571. goto Exit;
  572. }
  573. ZeroMemory(szExeName, MAX_STRESS_URL);
  574. // ******************************
  575. // ** Remove the file extension of the stressExe name and send the system and process
  576. // ** memory log to the command server
  577. WideCharToMultiByte(
  578. CP_ACP,
  579. NULL,
  580. g_hThis->m_szStressExe_FileName,
  581. -1,
  582. szExeName,
  583. MAX_STRESS_URL,
  584. NULL,
  585. NULL);
  586. MemStats__SendSystemMemoryLog(szExeName, g_hThis->m_piStressExeProcess.dwProcessId, g_hThis->Get_ID());
  587. Exit:
  588. delete [] szExeName;
  589. return;
  590. }
  591. ////////////////////////////////////////////////////////////
  592. // Function: DebuggerCallbackProc(DWORD, LPVOID, LPTSTR, LPVOID)
  593. //
  594. // Purpose:
  595. // Creates a memory dump on second change exceptions
  596. //
  597. ////////////////////////////////////////////////////////////
  598. DWORD DebuggerCallbackProc(
  599. DWORD dwFlags,
  600. LPVOID lpIn,
  601. LPTSTR lpszFutureString,
  602. LPVOID lpFuturePointer
  603. )
  604. {
  605. //test callback for debugger lib
  606. DWORD dwContinue = 0;
  607. // ***********************************
  608. // ***********************************
  609. // ** Check that the stressExe is still running.
  610. // **
  611. if (!g_hThis || !g_hThis->IsRunning(STRESSINSTANCE_STRESS_EXE_CLOSE_TIMEOUT))
  612. {
  613. dwContinue = DEBUGGER_CONTINUE_STOP_DEBUGGING;
  614. goto Exit;
  615. }
  616. switch (dwFlags)
  617. {
  618. case DEBUGGER_FIRST_CHANCE_EXCEPTION:
  619. NetworkTools__SendLog(FIELDNAME__LOGTYPE_INFORMATION, "FIRST_CHANCE_EXCEPTION detected.", NULL, g_hThis->Get_ID());
  620. //must use this to pass on first chance exceptions to the system
  621. dwContinue = DEBUGGER_CONTINUE_UNHANDLED;
  622. break;
  623. case DEBUGGER_SECOND_CHANCE_EXCEPTION:
  624. NetworkTools__SendLog(FIELDNAME__LOGTYPE_INFORMATION, "SECOND_CHANCE_EXCEPTION detected.", NULL, g_hThis->Get_ID());
  625. // build directory to copy dump file
  626. LPTSTR szPath;
  627. LPTSTR szNum;
  628. LPTSTR szMachineName;
  629. szPath = new TCHAR[MAX_PATH * 2];
  630. szNum = new TCHAR[100];
  631. szMachineName = new TCHAR[MAX_PATH];
  632. // ******************************
  633. // create the directory STRESSINSTANCE_MEMORY_DUMP_PATH\<MachineName>
  634. MultiByteToWideChar(
  635. CP_ACP,
  636. MB_PRECOMPOSED,
  637. g_objServerCommands.Get_ClientMachineName(),
  638. -1,
  639. szMachineName,
  640. MAX_PATH);
  641. // if the server sent a vaild path then use it, else use the default memory dump path
  642. if (0 < _tcslen(g_hThis->Get_StressExeMemoryDumpPath()))
  643. _tcscpy(szPath, g_hThis->Get_StressExeMemoryDumpPath());
  644. else
  645. _tcscpy(szPath, STRESSINSTANCE_DEFAULT_MEMORY_DUMP_PATH);
  646. // add the machine name to the end of the directory
  647. _tcscat(szPath, szMachineName);
  648. CreateDirectory(szPath, NULL);
  649. // ******************************
  650. // create the filename in form "<stressExeFileName>-<stressInstanceID>-<PID>.dmp"
  651. _tcscat(szPath, _T("\\"));
  652. _tcscat(szPath, g_hThis->m_szStressExe_FileName);
  653. _tcscat(szPath, _T("-"));
  654. _itot(g_hThis->Get_ID(), szNum, 10);
  655. _tcscat(szPath, szNum);
  656. _tcscat(szPath, _T("-"));
  657. _itot(g_hThis->m_piStressExeProcess.dwProcessId, szNum, 10);
  658. _tcscat(szPath, szNum);
  659. _tcscat(szPath, _T(".dmp"));
  660. //this creates a full user dump
  661. g_hThis->m_objDebugger->CreateMiniDump(szPath, _T("This is a full user dump created by debugger.lib"), DEBUGGER_CREATE_FULL_MINI_DUMP);
  662. delete [] szPath;
  663. delete [] szNum;
  664. delete [] szMachineName;
  665. // let the Command Server know a dump file was created
  666. NetworkTools__SendLog(FIELDNAME__LOGTYPE_DUMPFILE_CREATED, "User dump file was created.", NULL, g_hThis->Get_ID());
  667. // stop the debugger
  668. dwContinue = DEBUGGER_CONTINUE_STOP_DEBUGGING;
  669. break;
  670. case DEBUGGER_EXIT_PROCESS:
  671. dwContinue = DEBUGGER_CONTINUE_STOP_DEBUGGING;
  672. break;
  673. default:
  674. // let the Command Server know a dump file was created
  675. break;
  676. }
  677. Exit:
  678. return dwContinue;
  679. }