Description:
updated box for windows to prevent error modal dialog
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r131:d5c4e1d8daa2 - - 1 file changed: 3 inserted, 0 deleted

@@ -1,450 +1,453
1 /*
1 /*
2 This sandbox module is from [Fossil
2 This sandbox module is from [Fossil
3 grader](http://code.google.com/p/fossil-grader/).
3 grader](http://code.google.com/p/fossil-grader/).
4
4
5 This library is a modification from a program called trun, taken
5 This library is a modification from a program called trun, taken
6 from an unknown source. (FIX THIS)
6 from an unknown source. (FIX THIS)
7
7
8 When compiling with Mingw, add "-lpsapi" to link Windows'memory stat
8 When compiling with Mingw, add "-lpsapi" to link Windows'memory stat
9 library.
9 library.
10 */
10 */
11 #include <windows.h>
11 #include <windows.h>
12 #include <psapi.h>
12 #include <psapi.h>
13 #include <tlhelp32.h>
13 #include <tlhelp32.h>
14 #include <stdio.h>
14 #include <stdio.h>
15 #include "execute.h"
15 #include "execute.h"
16
16
17 #define INITIAL_WAIT_FOR_MEM_CHECK 100
17 #define INITIAL_WAIT_FOR_MEM_CHECK 100
18
18
19 /*
19 /*
20 ==How execute works==
20 ==How execute works==
21
21
22 ===Start up===
22 ===Start up===
23 Set up basic configurations: input file, output file
23 Set up basic configurations: input file, output file
24 into STARTUPINFO struct to be passed to CreateProcess.
24 into STARTUPINFO struct to be passed to CreateProcess.
25
25
26 Create a child process with CreateProcess.
26 Create a child process with CreateProcess.
27
27
28 ===Wait===
28 ===Wait===
29 Use WaitForSingleObject to wait.
29 Use WaitForSingleObject to wait.
30
30
31 ===Killing chile process===
31 ===Killing chile process===
32 This process is really involved, because (1) programs in
32 This process is really involved, because (1) programs in
33 DOS mode actually runs inside NTVDM so killing them
33 DOS mode actually runs inside NTVDM so killing them
34 requires to kill NTVDM, (2) something a program crashes
34 requires to kill NTVDM, (2) something a program crashes
35 NTVDM and a dialog box pops up, and we need to close
35 NTVDM and a dialog box pops up, and we need to close
36 that dialog box MANUALLY, and (3) for Win32 apps that crash,
36 that dialog box MANUALLY, and (3) for Win32 apps that crash,
37 some reporting service in Windows opens a dialog box,
37 some reporting service in Windows opens a dialog box,
38 and it has to be killed.
38 and it has to be killed.
39
39
40 Those extra steps are what's exactly done here:
40 Those extra steps are what's exactly done here:
41 1. Kill the process if there's any
41 1. Kill the process if there's any
42 2. In case that there's no real process, find NTVDM
42 2. In case that there's no real process, find NTVDM
43 and kill it (repeatedly until it's gone)
43 and kill it (repeatedly until it's gone)
44 3. Check if NTVDM crashed and some warning dialog opens,
44 3. Check if NTVDM crashed and some warning dialog opens,
45 if there's any, signal the user and wait.
45 if there's any, signal the user and wait.
46 4. For real Win32 apps, find process "dwwin.exe" which
46 4. For real Win32 apps, find process "dwwin.exe" which
47 represents an agent for reporting service and also
47 represents an agent for reporting service and also
48 opens a dialog. If finds it, kill it (repeatedly)
48 opens a dialog. If finds it, kill it (repeatedly)
49 until it's gone.
49 until it's gone.
50
50
51 Step 4. might be problematic --- dwwin.exe might not
51 Step 4. might be problematic --- dwwin.exe might not
52 be a universal process for error reporting services???
52 be a universal process for error reporting services???
53 */
53 */
54
54
55
55
56
56
57 /*
57 /*
58 These are routines that check NTVDM crash dialog.
58 These are routines that check NTVDM crash dialog.
59 It works by enumerating all window titles, and
59 It works by enumerating all window titles, and
60 checks for "16 bit" or something with ".exe" somewhere
60 checks for "16 bit" or something with ".exe" somewhere
61 and starts with "cmd.exe".
61 and starts with "cmd.exe".
62 */
62 */
63 bool NTVDMcrashed_found;
63 bool NTVDMcrashed_found;
64
64
65 /* this is a callback for window title enumeration */
65 /* this is a callback for window title enumeration */
66 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
66 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
67 {
67 {
68 char buffer[256];
68 char buffer[256];
69 GetWindowText(hWnd, buffer, 256);
69 GetWindowText(hWnd, buffer, 256);
70
70
71 if(strlen(buffer)!=0) {
71 if(strlen(buffer)!=0) {
72 if(strstr(buffer,"16 bit")!=0) {
72 if(strstr(buffer,"16 bit")!=0) {
73 NTVDMcrashed_found = true;
73 NTVDMcrashed_found = true;
74 }
74 }
75 if((strstr(buffer,".exe")!=0) &&
75 if((strstr(buffer,".exe")!=0) &&
76 (strstr(buffer,"cmd.exe")==buffer)) {
76 (strstr(buffer,"cmd.exe")==buffer)) {
77 NTVDMcrashed_found = true;
77 NTVDMcrashed_found = true;
78 printf("Title: %s\n",buffer);
78 printf("Title: %s\n",buffer);
79 }
79 }
80 }
80 }
81 return TRUE;
81 return TRUE;
82 }
82 }
83
83
84 bool check_ntvdm_dialog()
84 bool check_ntvdm_dialog()
85 {
85 {
86 NTVDMcrashed_found = false;
86 NTVDMcrashed_found = false;
87
87
88 FARPROC EnumProcInstance = MakeProcInstance((FARPROC)EnumWindowsProc,
88 FARPROC EnumProcInstance = MakeProcInstance((FARPROC)EnumWindowsProc,
89 AfxGetInstanceHandle());
89 AfxGetInstanceHandle());
90 EnumWindows((WNDENUMPROC)EnumProcInstance, (LPARAM)0);
90 EnumWindows((WNDENUMPROC)EnumProcInstance, (LPARAM)0);
91 FreeProcInstance(EnumProcInstance);
91 FreeProcInstance(EnumProcInstance);
92
92
93 return NTVDMcrashed_found;
93 return NTVDMcrashed_found;
94 }
94 }
95
95
96 DWORD get_process_id(char *pname)
96 DWORD get_process_id(char *pname)
97 {
97 {
98 HANDLE hProcessSnap;
98 HANDLE hProcessSnap;
99 HANDLE hProcess;
99 HANDLE hProcess;
100 PROCESSENTRY32 pe32;
100 PROCESSENTRY32 pe32;
101 DWORD dwPriorityClass;
101 DWORD dwPriorityClass;
102 DWORD pid=0;
102 DWORD pid=0;
103
103
104 hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
104 hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
105 if( hProcessSnap == INVALID_HANDLE_VALUE ) {
105 if( hProcessSnap == INVALID_HANDLE_VALUE ) {
106 return 0;
106 return 0;
107 }
107 }
108
108
109 pe32.dwSize = sizeof( PROCESSENTRY32 );
109 pe32.dwSize = sizeof( PROCESSENTRY32 );
110 if( !Process32First( hProcessSnap, &pe32 ) ) {
110 if( !Process32First( hProcessSnap, &pe32 ) ) {
111 CloseHandle( hProcessSnap );
111 CloseHandle( hProcessSnap );
112 return 0;
112 return 0;
113 }
113 }
114
114
115 do {
115 do {
116 if(strcasecmp(pe32.szExeFile ,pname)==0)
116 if(strcasecmp(pe32.szExeFile ,pname)==0)
117 pid = pe32.th32ProcessID;
117 pid = pe32.th32ProcessID;
118 } while( Process32Next( hProcessSnap, &pe32 ) );
118 } while( Process32Next( hProcessSnap, &pe32 ) );
119
119
120 CloseHandle( hProcessSnap );
120 CloseHandle( hProcessSnap );
121 return pid;
121 return pid;
122 }
122 }
123
123
124 DWORD get_ntvdm_pid()
124 DWORD get_ntvdm_pid()
125 {
125 {
126 return get_process_id("ntvdm.exe");
126 return get_process_id("ntvdm.exe");
127 }
127 }
128
128
129 void kill_error_report()
129 void kill_error_report()
130 {
130 {
131 DWORD pid;
131 DWORD pid;
132 do {
132 do {
133 if((pid = get_process_id("dwwin.exe"))!=0) {
133 if((pid = get_process_id("dwwin.exe"))!=0) {
134 fprintf(stderr," -- with error report (pid: %ld)\n",pid);
134 fprintf(stderr," -- with error report (pid: %ld)\n",pid);
135 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid);
135 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid);
136 if(hProcess!=NULL) {
136 if(hProcess!=NULL) {
137 TerminateProcess(hProcess, 0);
137 TerminateProcess(hProcess, 0);
138 Sleep(500);
138 Sleep(500);
139 while(get_process_id("dwwin.exe")==pid) {
139 while(get_process_id("dwwin.exe")==pid) {
140 fprintf(stderr,"wait for dwwin.exe to die...\n");
140 fprintf(stderr,"wait for dwwin.exe to die...\n");
141 Sleep(500);
141 Sleep(500);
142 }
142 }
143 } else
143 } else
144 fprintf(stderr,"do not have permission (%d)\n",
144 fprintf(stderr,"do not have permission (%d)\n",
145 GetLastError());
145 GetLastError());
146 }
146 }
147 } while(get_process_id("dwwin.exe")!=0);
147 } while(get_process_id("dwwin.exe")!=0);
148 }
148 }
149
149
150 void wait_dialog()
150 void wait_dialog()
151 {
151 {
152 kill_error_report();
152 kill_error_report();
153 if(check_ntvdm_dialog()) {
153 if(check_ntvdm_dialog()) {
154 fprintf(stderr,"Some dialog opens; please MANUALLY kill it.");
154 fprintf(stderr,"Some dialog opens; please MANUALLY kill it.");
155 fflush(stderr);
155 fflush(stderr);
156 do {
156 do {
157 Sleep(1000);
157 Sleep(1000);
158 } while(check_ntvdm_dialog());
158 } while(check_ntvdm_dialog());
159 fprintf(stderr,"... done\n");
159 fprintf(stderr,"... done\n");
160 }
160 }
161 }
161 }
162
162
163 void setstartupinfo(STARTUPINFO *si, char *inname, char *outname)
163 void setstartupinfo(STARTUPINFO *si, char *inname, char *outname)
164 {
164 {
165 SECURITY_ATTRIBUTES sa;
165 SECURITY_ATTRIBUTES sa;
166
166
167 ZeroMemory(&sa, sizeof(sa));
167 ZeroMemory(&sa, sizeof(sa));
168 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
168 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
169 sa.lpSecurityDescriptor = NULL;
169 sa.lpSecurityDescriptor = NULL;
170 sa.bInheritHandle = TRUE;
170 sa.bInheritHandle = TRUE;
171
171
172 si->dwFlags = STARTF_USESTDHANDLES;
172 si->dwFlags = STARTF_USESTDHANDLES;
173 if((inname!=0) && (strcmp(inname,"-")!=0)) {
173 if((inname!=0) && (strcmp(inname,"-")!=0)) {
174 si->hStdInput = CreateFile(inname,
174 si->hStdInput = CreateFile(inname,
175 FILE_READ_DATA,
175 FILE_READ_DATA,
176 FILE_SHARE_READ,
176 FILE_SHARE_READ,
177 &sa,
177 &sa,
178 OPEN_EXISTING,
178 OPEN_EXISTING,
179 FILE_ATTRIBUTE_NORMAL,
179 FILE_ATTRIBUTE_NORMAL,
180 NULL);
180 NULL);
181 } else
181 } else
182 si->hStdInput = NULL;
182 si->hStdInput = NULL;
183
183
184 if((outname!=0) && (strcmp(outname,"-")!=0)) {
184 if((outname!=0) && (strcmp(outname,"-")!=0)) {
185 si->hStdOutput = CreateFile(outname,
185 si->hStdOutput = CreateFile(outname,
186 FILE_WRITE_DATA,
186 FILE_WRITE_DATA,
187 FILE_SHARE_READ,
187 FILE_SHARE_READ,
188 &sa,
188 &sa,
189 CREATE_ALWAYS,
189 CREATE_ALWAYS,
190 FILE_ATTRIBUTE_NORMAL,
190 FILE_ATTRIBUTE_NORMAL,
191 NULL);
191 NULL);
192 } else
192 } else
193 si->hStdOutput = NULL;
193 si->hStdOutput = NULL;
194
194
195 si->hStdError = NULL;
195 si->hStdError = NULL;
196 }
196 }
197
197
198 // taken from http://msdn.microsoft.com/en-us/library/ms682050(VS.85).aspx
198 // taken from http://msdn.microsoft.com/en-us/library/ms682050(VS.85).aspx
199 void PrintMemoryInfo(DWORD processID)
199 void PrintMemoryInfo(DWORD processID)
200 {
200 {
201 HANDLE hProcess;
201 HANDLE hProcess;
202 PROCESS_MEMORY_COUNTERS pmc;
202 PROCESS_MEMORY_COUNTERS pmc;
203
203
204 // Print the process identifier.
204 // Print the process identifier.
205
205
206 printf("\nProcess ID: %u\n", processID);
206 printf("\nProcess ID: %u\n", processID);
207
207
208 // Print information about the memory usage of the process.
208 // Print information about the memory usage of the process.
209
209
210 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
210 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
211 PROCESS_VM_READ,
211 PROCESS_VM_READ,
212 FALSE,processID);
212 FALSE,processID);
213 if(hProcess == NULL)
213 if(hProcess == NULL)
214 return;
214 return;
215
215
216 if(GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
216 if(GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
217 printf("\tPageFaultCount: %d\n",pmc.PageFaultCount);
217 printf("\tPageFaultCount: %d\n",pmc.PageFaultCount);
218 printf("\tPeakWorkingSetSize: %d\n",
218 printf("\tPeakWorkingSetSize: %d\n",
219 pmc.PeakWorkingSetSize);
219 pmc.PeakWorkingSetSize);
220 printf("\tWorkingSetSize: %d\n",pmc.WorkingSetSize);
220 printf("\tWorkingSetSize: %d\n",pmc.WorkingSetSize);
221 printf("\tQuotaPeakPagedPoolUsage: %d\n",
221 printf("\tQuotaPeakPagedPoolUsage: %d\n",
222 pmc.QuotaPeakPagedPoolUsage);
222 pmc.QuotaPeakPagedPoolUsage);
223 printf("\tQuotaPagedPoolUsage: %d\n",
223 printf("\tQuotaPagedPoolUsage: %d\n",
224 pmc.QuotaPagedPoolUsage);
224 pmc.QuotaPagedPoolUsage);
225 printf("\tQuotaPeakNonPagedPoolUsage: %d\n",
225 printf("\tQuotaPeakNonPagedPoolUsage: %d\n",
226 pmc.QuotaPeakNonPagedPoolUsage);
226 pmc.QuotaPeakNonPagedPoolUsage);
227 printf("\tQuotaNonPagedPoolUsage: %d\n",
227 printf("\tQuotaNonPagedPoolUsage: %d\n",
228 pmc.QuotaNonPagedPoolUsage);
228 pmc.QuotaNonPagedPoolUsage);
229 printf("\tPagefileUsage: %d\n",pmc.PagefileUsage);
229 printf("\tPagefileUsage: %d\n",pmc.PagefileUsage);
230 printf("\tPeakPagefileUsage: %d\n",
230 printf("\tPeakPagefileUsage: %d\n",
231 pmc.PeakPagefileUsage);
231 pmc.PeakPagefileUsage);
232 }
232 }
233 CloseHandle( hProcess );
233 CloseHandle( hProcess );
234 }
234 }
235
235
236 int check_memory_usage(DWORD pid, int max_mem, int *actual_usage) {
236 int check_memory_usage(DWORD pid, int max_mem, int *actual_usage) {
237 // modified from http://msdn.microsoft.com/en-us/library/ms682050(VS.85).aspx
237 // modified from http://msdn.microsoft.com/en-us/library/ms682050(VS.85).aspx
238 //PrintMemoryInfo(pid);
238 //PrintMemoryInfo(pid);
239 HANDLE hProcess;
239 HANDLE hProcess;
240 PROCESS_MEMORY_COUNTERS pmc;
240 PROCESS_MEMORY_COUNTERS pmc;
241
241
242 if((max_mem==0) || (pid==0))
242 if((max_mem==0) || (pid==0))
243 return 1;
243 return 1;
244
244
245 if(pid == get_ntvdm_pid()) {
245 if(pid == get_ntvdm_pid()) {
246 fprintf(stderr,"ntvdm: ignored\n");
246 fprintf(stderr,"ntvdm: ignored\n");
247 return 1;
247 return 1;
248 }
248 }
249
249
250 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
250 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
251 PROCESS_VM_READ,
251 PROCESS_VM_READ,
252 FALSE, pid);
252 FALSE, pid);
253 if(hProcess == NULL)
253 if(hProcess == NULL)
254 return 1;
254 return 1;
255
255
256 int max_mem_usage = 0;
256 int max_mem_usage = 0;
257 if(GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
257 if(GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
258 max_mem_usage = pmc.PeakWorkingSetSize;
258 max_mem_usage = pmc.PeakWorkingSetSize;
259 if(pmc.PeakPagefileUsage > max_mem_usage)
259 if(pmc.PeakPagefileUsage > max_mem_usage)
260 max_mem_usage = pmc.PeakPagefileUsage;
260 max_mem_usage = pmc.PeakPagefileUsage;
261 }
261 }
262 CloseHandle(hProcess);
262 CloseHandle(hProcess);
263 if(actual_usage != NULL)
263 if(actual_usage != NULL)
264 (*actual_usage) = max_mem_usage;
264 (*actual_usage) = max_mem_usage;
265 return (max_mem_usage <= max_mem);
265 return (max_mem_usage <= max_mem);
266 }
266 }
267
267
268 void report_stat(double time_used, int memory_used)
268 void report_stat(double time_used, int memory_used)
269 {
269 {
270 fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dm\n",
270 fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dm\n",
271 time_used,
271 time_used,
272 time_used, (double)0,
272 time_used, (double)0,
273 memory_used);
273 memory_used);
274 }
274 }
275
275
276 double get_process_time_usage(HANDLE hProcess)
276 double get_process_time_usage(HANDLE hProcess)
277 {
277 {
278 FILETIME creation_time;
278 FILETIME creation_time;
279 FILETIME exit_time;
279 FILETIME exit_time;
280 FILETIME kernel_time;
280 FILETIME kernel_time;
281 FILETIME user_time;
281 FILETIME user_time;
282 GetProcessTimes(hProcess,
282 GetProcessTimes(hProcess,
283 &creation_time,
283 &creation_time,
284 &exit_time,
284 &exit_time,
285 &kernel_time,
285 &kernel_time,
286 &user_time);
286 &user_time);
287
287
288 SYSTEMTIME sys_kernel_time;
288 SYSTEMTIME sys_kernel_time;
289 SYSTEMTIME sys_user_time;
289 SYSTEMTIME sys_user_time;
290 FileTimeToSystemTime(&kernel_time, &sys_kernel_time);
290 FileTimeToSystemTime(&kernel_time, &sys_kernel_time);
291 FileTimeToSystemTime(&user_time, &sys_user_time);
291 FileTimeToSystemTime(&user_time, &sys_user_time);
292
292
293 double time_used =
293 double time_used =
294 ((sys_kernel_time.wSecond + sys_kernel_time.wMilliseconds/1000.0) +
294 ((sys_kernel_time.wSecond + sys_kernel_time.wMilliseconds/1000.0) +
295 (sys_user_time.wSecond + sys_user_time.wMilliseconds/1000.0));
295 (sys_user_time.wSecond + sys_user_time.wMilliseconds/1000.0));
296 return time_used;
296 return time_used;
297 }
297 }
298
298
299 int execute(char *exname, char *inname, char *outname, double t, int max_mem)
299 int execute(char *exname, char *inname, char *outname, double t, int max_mem)
300 {
300 {
301 STARTUPINFO si;
301 STARTUPINFO si;
302 PROCESS_INFORMATION pi;
302 PROCESS_INFORMATION pi;
303 int ifsuccess = EXE_RESULT_OK;
303 int ifsuccess = EXE_RESULT_OK;
304
304
305 + SetErrorMode(SEM_FAILCRITICALERRORS);
306 + SetErrorMode(SEM_NOGPFAULTERRORBOX);
307 +
305 ZeroMemory(&si, sizeof(si));
308 ZeroMemory(&si, sizeof(si));
306 si.cb = sizeof(si);
309 si.cb = sizeof(si);
307 ZeroMemory(&pi, sizeof(pi));
310 ZeroMemory(&pi, sizeof(pi));
308
311
309 setstartupinfo(&si, inname, outname);
312 setstartupinfo(&si, inname, outname);
310
313
311 if(!CreateProcess( NULL, // No module name (use command line).
314 if(!CreateProcess( NULL, // No module name (use command line).
312 TEXT(exname), // Command line.
315 TEXT(exname), // Command line.
313 NULL, // Process handle not inheritable.
316 NULL, // Process handle not inheritable.
314 NULL, // Thread handle not inheritable.
317 NULL, // Thread handle not inheritable.
315 TRUE, // Set handle inheritance to FALSE.
318 TRUE, // Set handle inheritance to FALSE.
316 0, // No creation flags.
319 0, // No creation flags.
317 NULL, // Use parent's environment block.
320 NULL, // Use parent's environment block.
318 NULL, // Use parent's starting directory.
321 NULL, // Use parent's starting directory.
319 &si, // Pointer to STARTUPINFO structure.
322 &si, // Pointer to STARTUPINFO structure.
320 &pi)) // Pointer to PROCESS_INFORMATION structure.
323 &pi)) // Pointer to PROCESS_INFORMATION structure.
321 {
324 {
322 //printf( "CreateProcess failed (%d).\n", GetLastError() );
325 //printf( "CreateProcess failed (%d).\n", GetLastError() );
323 fprintf(stderr, "Process creation error.\n");
326 fprintf(stderr, "Process creation error.\n");
324 report_stat(0,0);
327 report_stat(0,0);
325 return EXE_RESULT_ERROR;
328 return EXE_RESULT_ERROR;
326 }
329 }
327 //fprintf(stderr,"Process ID: %ld\n",pi.dwProcessId);
330 //fprintf(stderr,"Process ID: %ld\n",pi.dwProcessId);
328 //fprintf(stderr,"time limit = %d\n",t);
331 //fprintf(stderr,"time limit = %d\n",t);
329
332
330 // checking memory usage
333 // checking memory usage
331 // wait 0.1 sec before checking mem usage
334 // wait 0.1 sec before checking mem usage
332
335
333 SetProcessWorkingSetSize(pi.hProcess,
336 SetProcessWorkingSetSize(pi.hProcess,
334 1,
337 1,
335 max_mem);
338 max_mem);
336 int actual_memory_usage = 0;
339 int actual_memory_usage = 0;
337
340
338 Sleep(INITIAL_WAIT_FOR_MEM_CHECK);
341 Sleep(INITIAL_WAIT_FOR_MEM_CHECK);
339 if(!check_memory_usage(pi.dwProcessId,max_mem,&actual_memory_usage)) {
342 if(!check_memory_usage(pi.dwProcessId,max_mem,&actual_memory_usage)) {
340 // using too much memory
343 // using too much memory
341 fprintf(stderr,"Memory limit exceeded.\n");
344 fprintf(stderr,"Memory limit exceeded.\n");
342 //PrintMemoryInfo(pi.dwProcessId);
345 //PrintMemoryInfo(pi.dwProcessId);
343 ifsuccess = EXE_RESULT_MEMORY;
346 ifsuccess = EXE_RESULT_MEMORY;
344 }
347 }
345
348
346 //printf("PID: %d\n", pi.dwProcessId);
349 //printf("PID: %d\n", pi.dwProcessId);
347
350
348 if(ifsuccess != EXE_RESULT_MEMORY) {
351 if(ifsuccess != EXE_RESULT_MEMORY) {
349 int based_time = (int)(t*1000) + 1 - INITIAL_WAIT_FOR_MEM_CHECK;
352 int based_time = (int)(t*1000) + 1 - INITIAL_WAIT_FOR_MEM_CHECK;
350 bool major_timed_out = (WaitForSingleObject(pi.hProcess,
353 bool major_timed_out = (WaitForSingleObject(pi.hProcess,
351 based_time)==WAIT_TIMEOUT);
354 based_time)==WAIT_TIMEOUT);
352 if(major_timed_out) {
355 if(major_timed_out) {
353 // wait some more for user time.
356 // wait some more for user time.
354 double time_used = get_process_time_usage(pi.hProcess);
357 double time_used = get_process_time_usage(pi.hProcess);
355 while(time_used <= t) {
358 while(time_used <= t) {
356 int iter_time = 100;
359 int iter_time = 100;
357 if(t - time_used < 200)
360 if(t - time_used < 200)
358 iter_time = 20;
361 iter_time = 20;
359 bool iter_timed_out = (WaitForSingleObject(pi.hProcess,
362 bool iter_timed_out = (WaitForSingleObject(pi.hProcess,
360 iter_time)==WAIT_TIMEOUT);
363 iter_time)==WAIT_TIMEOUT);
361 if(!iter_timed_out)
364 if(!iter_timed_out)
362 break;
365 break;
363
366
364 time_used = get_process_time_usage(pi.hProcess);
367 time_used = get_process_time_usage(pi.hProcess);
365 //printf("%lf\n",time_used);
368 //printf("%lf\n",time_used);
366 }
369 }
367 ifsuccess = EXE_RESULT_TIMEOUT;
370 ifsuccess = EXE_RESULT_TIMEOUT;
368 }
371 }
369 }
372 }
370
373
371 if((ifsuccess == EXE_RESULT_MEMORY) || (ifsuccess == EXE_RESULT_TIMEOUT)) {
374 if((ifsuccess == EXE_RESULT_MEMORY) || (ifsuccess == EXE_RESULT_TIMEOUT)) {
372 // Kill process, because (1) it used too much memory, or (2) time limit
375 // Kill process, because (1) it used too much memory, or (2) time limit
373 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
376 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
374
377
375 if(ifsuccess != EXE_RESULT_MEMORY)
378 if(ifsuccess != EXE_RESULT_MEMORY)
376 fprintf(stderr,"Time limit exceeded.\n");
379 fprintf(stderr,"Time limit exceeded.\n");
377 if(hProcess != NULL) {
380 if(hProcess != NULL) {
378 fprintf(stderr,"killing pid: %ld\n",pi.dwProcessId);
381 fprintf(stderr,"killing pid: %ld\n",pi.dwProcessId);
379 TerminateProcess(hProcess, 0);
382 TerminateProcess(hProcess, 0);
380 wait_dialog();
383 wait_dialog();
381 } else {
384 } else {
382 DWORD dwNtvdmId = get_ntvdm_pid();
385 DWORD dwNtvdmId = get_ntvdm_pid();
383 fprintf(stderr,"killing (ntvdm) pid: %ld\n",dwNtvdmId);
386 fprintf(stderr,"killing (ntvdm) pid: %ld\n",dwNtvdmId);
384 if(dwNtvdmId!=0) {
387 if(dwNtvdmId!=0) {
385 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwNtvdmId);
388 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwNtvdmId);
386 TerminateProcess(hProcess, 0);
389 TerminateProcess(hProcess, 0);
387 } else {
390 } else {
388 fprintf(stderr,"killing process error\n");
391 fprintf(stderr,"killing process error\n");
389 }
392 }
390
393
391 if(get_ntvdm_pid()!=0) {
394 if(get_ntvdm_pid()!=0) {
392 fprintf(stderr,"killing error, ntvdm.exe still remains;");
395 fprintf(stderr,"killing error, ntvdm.exe still remains;");
393 fprintf(stderr,"please MANUALLY kill it.");
396 fprintf(stderr,"please MANUALLY kill it.");
394 fflush(stderr);
397 fflush(stderr);
395 do {
398 do {
396 Sleep(1000);
399 Sleep(1000);
397 } while(get_ntvdm_pid()!=0);
400 } while(get_ntvdm_pid()!=0);
398 fprintf(stderr,"... done\n");
401 fprintf(stderr,"... done\n");
399 wait_dialog();
402 wait_dialog();
400 }
403 }
401 }
404 }
402 if(ifsuccess != EXE_RESULT_MEMORY)
405 if(ifsuccess != EXE_RESULT_MEMORY)
403 ifsuccess = EXE_RESULT_TIMEOUT;
406 ifsuccess = EXE_RESULT_TIMEOUT;
404 }
407 }
405
408
406 // check memory after terminated
409 // check memory after terminated
407 if((ifsuccess==EXE_RESULT_OK) &&
410 if((ifsuccess==EXE_RESULT_OK) &&
408 (!check_memory_usage(pi.dwProcessId,max_mem, &actual_memory_usage))) {
411 (!check_memory_usage(pi.dwProcessId,max_mem, &actual_memory_usage))) {
409 // using too much memory
412 // using too much memory
410 ifsuccess = EXE_RESULT_MEMORY;
413 ifsuccess = EXE_RESULT_MEMORY;
411 }
414 }
412
415
413 // check return code
416 // check return code
414 if(ifsuccess==EXE_RESULT_OK) {
417 if(ifsuccess==EXE_RESULT_OK) {
415 DWORD exitcode;
418 DWORD exitcode;
416 GetExitCodeProcess(pi.hProcess, &exitcode);
419 GetExitCodeProcess(pi.hProcess, &exitcode);
417 if(exitcode!=0) {
420 if(exitcode!=0) {
418 fprintf(stderr,"Exit status %d.\n", (int)exitcode);
421 fprintf(stderr,"Exit status %d.\n", (int)exitcode);
419 ifsuccess = EXE_RESULT_ERROR;
422 ifsuccess = EXE_RESULT_ERROR;
420 }
423 }
421 }
424 }
422
425
423 wait_dialog();
426 wait_dialog();
424
427
425 if(si.hStdInput!=NULL)
428 if(si.hStdInput!=NULL)
426 CloseHandle(si.hStdInput);
429 CloseHandle(si.hStdInput);
427 if(si.hStdOutput!=NULL)
430 if(si.hStdOutput!=NULL)
428 CloseHandle(si.hStdOutput);
431 CloseHandle(si.hStdOutput);
429
432
430 if(ifsuccess==EXE_RESULT_OK)
433 if(ifsuccess==EXE_RESULT_OK)
431 fprintf(stderr,"OK\n");
434 fprintf(stderr,"OK\n");
432 else if(ifsuccess==EXE_RESULT_TIMEOUT)
435 else if(ifsuccess==EXE_RESULT_TIMEOUT)
433 fprintf(stderr,"Time limit exceeded.\n");
436 fprintf(stderr,"Time limit exceeded.\n");
434 else if(ifsuccess==EXE_RESULT_MEMORY)
437 else if(ifsuccess==EXE_RESULT_MEMORY)
435 fprintf(stderr,"Memory limit exceeded.\n");
438 fprintf(stderr,"Memory limit exceeded.\n");
436
439
437 double actual_time_usage = get_process_time_usage(pi.hProcess);
440 double actual_time_usage = get_process_time_usage(pi.hProcess);
438 /*
441 /*
439 if(ifsuccess==EXE_RESULT_TIMEOUT)
442 if(ifsuccess==EXE_RESULT_TIMEOUT)
440 actual_time_usage = t+1;
443 actual_time_usage = t+1;
441 else
444 else
442 actual_time_usage = t;
445 actual_time_usage = t;
443 */
446 */
444
447
445 report_stat(actual_time_usage,
448 report_stat(actual_time_usage,
446 (actual_memory_usage + 1023)/1024);
449 (actual_memory_usage + 1023)/1024);
447
450
448 return ifsuccess;
451 return ifsuccess;
449 }
452 }
450
453
You need to be logged in to leave comments. Login now