Description:
box uses user time
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r130:db5312fad511 - - 1 file changed: 26 inserted, 4 deleted

@@ -1,428 +1,450
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 ZeroMemory(&si, sizeof(si));
305 ZeroMemory(&si, sizeof(si));
306 si.cb = sizeof(si);
306 si.cb = sizeof(si);
307 ZeroMemory(&pi, sizeof(pi));
307 ZeroMemory(&pi, sizeof(pi));
308
308
309 setstartupinfo(&si, inname, outname);
309 setstartupinfo(&si, inname, outname);
310
310
311 if(!CreateProcess( NULL, // No module name (use command line).
311 if(!CreateProcess( NULL, // No module name (use command line).
312 TEXT(exname), // Command line.
312 TEXT(exname), // Command line.
313 NULL, // Process handle not inheritable.
313 NULL, // Process handle not inheritable.
314 NULL, // Thread handle not inheritable.
314 NULL, // Thread handle not inheritable.
315 TRUE, // Set handle inheritance to FALSE.
315 TRUE, // Set handle inheritance to FALSE.
316 0, // No creation flags.
316 0, // No creation flags.
317 NULL, // Use parent's environment block.
317 NULL, // Use parent's environment block.
318 NULL, // Use parent's starting directory.
318 NULL, // Use parent's starting directory.
319 &si, // Pointer to STARTUPINFO structure.
319 &si, // Pointer to STARTUPINFO structure.
320 &pi)) // Pointer to PROCESS_INFORMATION structure.
320 &pi)) // Pointer to PROCESS_INFORMATION structure.
321 {
321 {
322 //printf( "CreateProcess failed (%d).\n", GetLastError() );
322 //printf( "CreateProcess failed (%d).\n", GetLastError() );
323 fprintf(stderr, "Process creation error.\n");
323 fprintf(stderr, "Process creation error.\n");
324 report_stat(0,0);
324 report_stat(0,0);
325 return EXE_RESULT_ERROR;
325 return EXE_RESULT_ERROR;
326 }
326 }
327 //fprintf(stderr,"Process ID: %ld\n",pi.dwProcessId);
327 //fprintf(stderr,"Process ID: %ld\n",pi.dwProcessId);
328 //fprintf(stderr,"time limit = %d\n",t);
328 //fprintf(stderr,"time limit = %d\n",t);
329
329
330 // checking memory usage
330 // checking memory usage
331 // wait 0.1 sec before checking mem usage
331 // wait 0.1 sec before checking mem usage
332
332
333 SetProcessWorkingSetSize(pi.hProcess,
333 SetProcessWorkingSetSize(pi.hProcess,
334 1,
334 1,
335 max_mem);
335 max_mem);
336 int actual_memory_usage = 0;
336 int actual_memory_usage = 0;
337
337
338 Sleep(INITIAL_WAIT_FOR_MEM_CHECK);
338 Sleep(INITIAL_WAIT_FOR_MEM_CHECK);
339 if(!check_memory_usage(pi.dwProcessId,max_mem,&actual_memory_usage)) {
339 if(!check_memory_usage(pi.dwProcessId,max_mem,&actual_memory_usage)) {
340 // using too much memory
340 // using too much memory
341 fprintf(stderr,"Memory limit exceeded.\n");
341 fprintf(stderr,"Memory limit exceeded.\n");
342 //PrintMemoryInfo(pi.dwProcessId);
342 //PrintMemoryInfo(pi.dwProcessId);
343 ifsuccess = EXE_RESULT_MEMORY;
343 ifsuccess = EXE_RESULT_MEMORY;
344 }
344 }
345
345
346 - if((ifsuccess == EXE_RESULT_MEMORY) ||
346 + //printf("PID: %d\n", pi.dwProcessId);
347 - (WaitForSingleObject(pi.hProcess,
347 +
348 - (int)(t*1000) + 1
348 + if(ifsuccess != EXE_RESULT_MEMORY) {
349 - - INITIAL_WAIT_FOR_MEM_CHECK)==WAIT_TIMEOUT)) {
349 + int based_time = (int)(t*1000) + 1 - INITIAL_WAIT_FOR_MEM_CHECK;
350 + bool major_timed_out = (WaitForSingleObject(pi.hProcess,
351 + based_time)==WAIT_TIMEOUT);
352 + if(major_timed_out) {
353 + // wait some more for user time.
354 + double time_used = get_process_time_usage(pi.hProcess);
355 + while(time_used <= t) {
356 + int iter_time = 100;
357 + if(t - time_used < 200)
358 + iter_time = 20;
359 + bool iter_timed_out = (WaitForSingleObject(pi.hProcess,
360 + iter_time)==WAIT_TIMEOUT);
361 + if(!iter_timed_out)
362 + break;
363 +
364 + time_used = get_process_time_usage(pi.hProcess);
365 + //printf("%lf\n",time_used);
366 + }
367 + ifsuccess = EXE_RESULT_TIMEOUT;
368 + }
369 + }
370 +
371 + if((ifsuccess == EXE_RESULT_MEMORY) || (ifsuccess == EXE_RESULT_TIMEOUT)) {
350 // Kill process, because (1) it used too much memory, or (2) time limit
372 // Kill process, because (1) it used too much memory, or (2) time limit
351 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
373 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
352
374
353 if(ifsuccess != EXE_RESULT_MEMORY)
375 if(ifsuccess != EXE_RESULT_MEMORY)
354 fprintf(stderr,"Time limit exceeded.\n");
376 fprintf(stderr,"Time limit exceeded.\n");
355 if(hProcess != NULL) {
377 if(hProcess != NULL) {
356 fprintf(stderr,"killing pid: %ld\n",pi.dwProcessId);
378 fprintf(stderr,"killing pid: %ld\n",pi.dwProcessId);
357 TerminateProcess(hProcess, 0);
379 TerminateProcess(hProcess, 0);
358 wait_dialog();
380 wait_dialog();
359 } else {
381 } else {
360 DWORD dwNtvdmId = get_ntvdm_pid();
382 DWORD dwNtvdmId = get_ntvdm_pid();
361 fprintf(stderr,"killing (ntvdm) pid: %ld\n",dwNtvdmId);
383 fprintf(stderr,"killing (ntvdm) pid: %ld\n",dwNtvdmId);
362 if(dwNtvdmId!=0) {
384 if(dwNtvdmId!=0) {
363 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwNtvdmId);
385 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwNtvdmId);
364 TerminateProcess(hProcess, 0);
386 TerminateProcess(hProcess, 0);
365 } else {
387 } else {
366 fprintf(stderr,"killing process error\n");
388 fprintf(stderr,"killing process error\n");
367 }
389 }
368
390
369 if(get_ntvdm_pid()!=0) {
391 if(get_ntvdm_pid()!=0) {
370 fprintf(stderr,"killing error, ntvdm.exe still remains;");
392 fprintf(stderr,"killing error, ntvdm.exe still remains;");
371 fprintf(stderr,"please MANUALLY kill it.");
393 fprintf(stderr,"please MANUALLY kill it.");
372 fflush(stderr);
394 fflush(stderr);
373 do {
395 do {
374 Sleep(1000);
396 Sleep(1000);
375 } while(get_ntvdm_pid()!=0);
397 } while(get_ntvdm_pid()!=0);
376 fprintf(stderr,"... done\n");
398 fprintf(stderr,"... done\n");
377 wait_dialog();
399 wait_dialog();
378 }
400 }
379 }
401 }
380 if(ifsuccess != EXE_RESULT_MEMORY)
402 if(ifsuccess != EXE_RESULT_MEMORY)
381 ifsuccess = EXE_RESULT_TIMEOUT;
403 ifsuccess = EXE_RESULT_TIMEOUT;
382 }
404 }
383
405
384 // check memory after terminated
406 // check memory after terminated
385 if((ifsuccess==EXE_RESULT_OK) &&
407 if((ifsuccess==EXE_RESULT_OK) &&
386 (!check_memory_usage(pi.dwProcessId,max_mem, &actual_memory_usage))) {
408 (!check_memory_usage(pi.dwProcessId,max_mem, &actual_memory_usage))) {
387 // using too much memory
409 // using too much memory
388 ifsuccess = EXE_RESULT_MEMORY;
410 ifsuccess = EXE_RESULT_MEMORY;
389 }
411 }
390
412
391 // check return code
413 // check return code
392 if(ifsuccess==EXE_RESULT_OK) {
414 if(ifsuccess==EXE_RESULT_OK) {
393 DWORD exitcode;
415 DWORD exitcode;
394 GetExitCodeProcess(pi.hProcess, &exitcode);
416 GetExitCodeProcess(pi.hProcess, &exitcode);
395 if(exitcode!=0) {
417 if(exitcode!=0) {
396 fprintf(stderr,"Exit status %d.\n", (int)exitcode);
418 fprintf(stderr,"Exit status %d.\n", (int)exitcode);
397 ifsuccess = EXE_RESULT_ERROR;
419 ifsuccess = EXE_RESULT_ERROR;
398 }
420 }
399 }
421 }
400
422
401 wait_dialog();
423 wait_dialog();
402
424
403 if(si.hStdInput!=NULL)
425 if(si.hStdInput!=NULL)
404 CloseHandle(si.hStdInput);
426 CloseHandle(si.hStdInput);
405 if(si.hStdOutput!=NULL)
427 if(si.hStdOutput!=NULL)
406 CloseHandle(si.hStdOutput);
428 CloseHandle(si.hStdOutput);
407
429
408 if(ifsuccess==EXE_RESULT_OK)
430 if(ifsuccess==EXE_RESULT_OK)
409 fprintf(stderr,"OK\n");
431 fprintf(stderr,"OK\n");
410 else if(ifsuccess==EXE_RESULT_TIMEOUT)
432 else if(ifsuccess==EXE_RESULT_TIMEOUT)
411 fprintf(stderr,"Time limit exceeded.\n");
433 fprintf(stderr,"Time limit exceeded.\n");
412 else if(ifsuccess==EXE_RESULT_MEMORY)
434 else if(ifsuccess==EXE_RESULT_MEMORY)
413 fprintf(stderr,"Memory limit exceeded.\n");
435 fprintf(stderr,"Memory limit exceeded.\n");
414
436
415 double actual_time_usage = get_process_time_usage(pi.hProcess);
437 double actual_time_usage = get_process_time_usage(pi.hProcess);
416 /*
438 /*
417 if(ifsuccess==EXE_RESULT_TIMEOUT)
439 if(ifsuccess==EXE_RESULT_TIMEOUT)
418 actual_time_usage = t+1;
440 actual_time_usage = t+1;
419 else
441 else
420 actual_time_usage = t;
442 actual_time_usage = t;
421 */
443 */
422
444
423 report_stat(actual_time_usage,
445 report_stat(actual_time_usage,
424 (actual_memory_usage + 1023)/1024);
446 (actual_memory_usage + 1023)/1024);
425
447
426 return ifsuccess;
448 return ifsuccess;
427 }
449 }
428
450
You need to be logged in to leave comments. Login now