Description:
reports running time, checks exit status; modified running time test case, memory test case.
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r114:e28e189186ff - - 4 files changed: 88 inserted, 19 deleted

@@ -1,377 +1,428
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)
269 + {
270 + fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dm\n",
271 + time_used,
272 + time_used, (double)0,
273 + memory_used);
274 + }
275 +
276 + double get_process_time_usage(HANDLE hProcess)
277 + {
278 + FILETIME creation_time;
279 + FILETIME exit_time;
280 + FILETIME kernel_time;
281 + FILETIME user_time;
282 + GetProcessTimes(hProcess,
283 + &creation_time,
284 + &exit_time,
285 + &kernel_time,
286 + &user_time);
287 +
288 + SYSTEMTIME sys_kernel_time;
289 + SYSTEMTIME sys_user_time;
290 + FileTimeToSystemTime(&kernel_time, &sys_kernel_time);
291 + FileTimeToSystemTime(&user_time, &sys_user_time);
292 +
293 + double time_used =
294 + ((sys_kernel_time.wSecond + sys_kernel_time.wMilliseconds/1000.0) +
295 + (sys_user_time.wSecond + sys_user_time.wMilliseconds/1000.0));
296 + return time_used;
297 + }
298 +
268 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)
269 {
300 {
270 STARTUPINFO si;
301 STARTUPINFO si;
271 PROCESS_INFORMATION pi;
302 PROCESS_INFORMATION pi;
272 int ifsuccess = EXE_RESULT_OK;
303 int ifsuccess = EXE_RESULT_OK;
273
304
274 ZeroMemory(&si, sizeof(si));
305 ZeroMemory(&si, sizeof(si));
275 si.cb = sizeof(si);
306 si.cb = sizeof(si);
276 ZeroMemory(&pi, sizeof(pi));
307 ZeroMemory(&pi, sizeof(pi));
277
308
278 setstartupinfo(&si, inname, outname);
309 setstartupinfo(&si, inname, outname);
279
310
280 if(!CreateProcess( NULL, // No module name (use command line).
311 if(!CreateProcess( NULL, // No module name (use command line).
281 TEXT(exname), // Command line.
312 TEXT(exname), // Command line.
282 NULL, // Process handle not inheritable.
313 NULL, // Process handle not inheritable.
283 NULL, // Thread handle not inheritable.
314 NULL, // Thread handle not inheritable.
284 TRUE, // Set handle inheritance to FALSE.
315 TRUE, // Set handle inheritance to FALSE.
285 0, // No creation flags.
316 0, // No creation flags.
286 NULL, // Use parent's environment block.
317 NULL, // Use parent's environment block.
287 NULL, // Use parent's starting directory.
318 NULL, // Use parent's starting directory.
288 &si, // Pointer to STARTUPINFO structure.
319 &si, // Pointer to STARTUPINFO structure.
289 &pi)) // Pointer to PROCESS_INFORMATION structure.
320 &pi)) // Pointer to PROCESS_INFORMATION structure.
290 {
321 {
291 //printf( "CreateProcess failed (%d).\n", GetLastError() );
322 //printf( "CreateProcess failed (%d).\n", GetLastError() );
323 + fprintf(stderr, "Process creation error.\n");
324 + report_stat(0,0);
325 + return EXE_RESULT_ERROR;
292 }
326 }
293 //fprintf(stderr,"Process ID: %ld\n",pi.dwProcessId);
327 //fprintf(stderr,"Process ID: %ld\n",pi.dwProcessId);
294 //fprintf(stderr,"time limit = %d\n",t);
328 //fprintf(stderr,"time limit = %d\n",t);
295
329
296 // checking memory usage
330 // checking memory usage
297 // wait 0.1 sec before checking mem usage
331 // wait 0.1 sec before checking mem usage
298 -
332 +
333 + SetProcessWorkingSetSize(pi.hProcess,
334 + 1,
335 + max_mem);
299 int actual_memory_usage = 0;
336 int actual_memory_usage = 0;
300
337
301 Sleep(INITIAL_WAIT_FOR_MEM_CHECK);
338 Sleep(INITIAL_WAIT_FOR_MEM_CHECK);
302 if(!check_memory_usage(pi.dwProcessId,max_mem,&actual_memory_usage)) {
339 if(!check_memory_usage(pi.dwProcessId,max_mem,&actual_memory_usage)) {
303 // using too much memory
340 // using too much memory
304 fprintf(stderr,"Memory limit exceeded.\n");
341 fprintf(stderr,"Memory limit exceeded.\n");
305 //PrintMemoryInfo(pi.dwProcessId);
342 //PrintMemoryInfo(pi.dwProcessId);
306 ifsuccess = EXE_RESULT_MEMORY;
343 ifsuccess = EXE_RESULT_MEMORY;
307 }
344 }
308
345
309 if((ifsuccess == EXE_RESULT_MEMORY) ||
346 if((ifsuccess == EXE_RESULT_MEMORY) ||
310 (WaitForSingleObject(pi.hProcess,
347 (WaitForSingleObject(pi.hProcess,
311 (int)(t*1000) + 1
348 (int)(t*1000) + 1
312 - INITIAL_WAIT_FOR_MEM_CHECK)==WAIT_TIMEOUT)) {
349 - INITIAL_WAIT_FOR_MEM_CHECK)==WAIT_TIMEOUT)) {
313 - // need to kill...
350 + // Kill process, because (1) it used too much memory, or (2) time limit
314 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
351 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
315
352
316 if(ifsuccess != EXE_RESULT_MEMORY)
353 if(ifsuccess != EXE_RESULT_MEMORY)
317 fprintf(stderr,"Time limit exceeded.\n");
354 fprintf(stderr,"Time limit exceeded.\n");
318 if(hProcess != NULL) {
355 if(hProcess != NULL) {
319 fprintf(stderr,"killing pid: %ld\n",pi.dwProcessId);
356 fprintf(stderr,"killing pid: %ld\n",pi.dwProcessId);
320 TerminateProcess(hProcess, 0);
357 TerminateProcess(hProcess, 0);
321 wait_dialog();
358 wait_dialog();
322 } else {
359 } else {
323 DWORD dwNtvdmId = get_ntvdm_pid();
360 DWORD dwNtvdmId = get_ntvdm_pid();
324 fprintf(stderr,"killing (ntvdm) pid: %ld\n",dwNtvdmId);
361 fprintf(stderr,"killing (ntvdm) pid: %ld\n",dwNtvdmId);
325 if(dwNtvdmId!=0) {
362 if(dwNtvdmId!=0) {
326 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwNtvdmId);
363 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwNtvdmId);
327 TerminateProcess(hProcess, 0);
364 TerminateProcess(hProcess, 0);
328 } else {
365 } else {
329 fprintf(stderr,"killing process error\n");
366 fprintf(stderr,"killing process error\n");
330 }
367 }
331
368
332 if(get_ntvdm_pid()!=0) {
369 if(get_ntvdm_pid()!=0) {
333 fprintf(stderr,"killing error, ntvdm.exe still remains;");
370 fprintf(stderr,"killing error, ntvdm.exe still remains;");
334 fprintf(stderr,"please MANUALLY kill it.");
371 fprintf(stderr,"please MANUALLY kill it.");
335 fflush(stderr);
372 fflush(stderr);
336 do {
373 do {
337 Sleep(1000);
374 Sleep(1000);
338 } while(get_ntvdm_pid()!=0);
375 } while(get_ntvdm_pid()!=0);
339 fprintf(stderr,"... done\n");
376 fprintf(stderr,"... done\n");
340 wait_dialog();
377 wait_dialog();
341 }
378 }
342 }
379 }
343 if(ifsuccess != EXE_RESULT_MEMORY)
380 if(ifsuccess != EXE_RESULT_MEMORY)
344 ifsuccess = EXE_RESULT_TIMEOUT;
381 ifsuccess = EXE_RESULT_TIMEOUT;
345 }
382 }
383 +
384 + // check memory after terminated
346 if((ifsuccess==EXE_RESULT_OK) &&
385 if((ifsuccess==EXE_RESULT_OK) &&
347 (!check_memory_usage(pi.dwProcessId,max_mem, &actual_memory_usage))) {
386 (!check_memory_usage(pi.dwProcessId,max_mem, &actual_memory_usage))) {
348 // using too much memory
387 // using too much memory
349 ifsuccess = EXE_RESULT_MEMORY;
388 ifsuccess = EXE_RESULT_MEMORY;
350 }
389 }
390 +
391 + // check return code
392 + if(ifsuccess==EXE_RESULT_OK) {
393 + DWORD exitcode;
394 + GetExitCodeProcess(pi.hProcess, &exitcode);
395 + if(exitcode!=0) {
396 + fprintf(stderr,"Exit status %d.\n", (int)exitcode);
397 + ifsuccess = EXE_RESULT_ERROR;
398 + }
399 + }
400 +
351 wait_dialog();
401 wait_dialog();
402 +
352 if(si.hStdInput!=NULL)
403 if(si.hStdInput!=NULL)
353 CloseHandle(si.hStdInput);
404 CloseHandle(si.hStdInput);
354 if(si.hStdOutput!=NULL)
405 if(si.hStdOutput!=NULL)
355 CloseHandle(si.hStdOutput);
406 CloseHandle(si.hStdOutput);
356
407
357 if(ifsuccess==EXE_RESULT_OK)
408 if(ifsuccess==EXE_RESULT_OK)
358 fprintf(stderr,"OK\n");
409 fprintf(stderr,"OK\n");
359 else if(ifsuccess==EXE_RESULT_TIMEOUT)
410 else if(ifsuccess==EXE_RESULT_TIMEOUT)
360 fprintf(stderr,"Time limit exceeded.\n");
411 fprintf(stderr,"Time limit exceeded.\n");
361 - else
412 + else if(ifsuccess==EXE_RESULT_MEMORY)
362 fprintf(stderr,"Memory limit exceeded.\n");
413 fprintf(stderr,"Memory limit exceeded.\n");
363
414
364 - double actual_time_usage;
415 + double actual_time_usage = get_process_time_usage(pi.hProcess);
416 + /*
365 if(ifsuccess==EXE_RESULT_TIMEOUT)
417 if(ifsuccess==EXE_RESULT_TIMEOUT)
366 actual_time_usage = t+1;
418 actual_time_usage = t+1;
367 else
419 else
368 actual_time_usage = t;
420 actual_time_usage = t;
421 + */
369
422
370 - fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dm\n",
423 + report_stat(actual_time_usage,
371 - actual_time_usage,
424 + (actual_memory_usage + 1023)/1024);
372 - actual_time_usage, (double)0,
373 - (actual_memory_usage + 1023)/1024);
374
425
375 return ifsuccess;
426 return ifsuccess;
376 }
427 }
377
428
@@ -1,25 +1,26
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 The code is a modification from an unknown source on the internet.
5 The code is a modification from an unknown source on the internet.
6
6
7 */
7 */
8 #ifndef EXECUTE_H_INCLUDED
8 #ifndef EXECUTE_H_INCLUDED
9 #define EXECUTE_H_INCLUDED
9 #define EXECUTE_H_INCLUDED
10
10
11 #define EXE_RESULT_OK 0
11 #define EXE_RESULT_OK 0
12 #define EXE_RESULT_TIMEOUT 1
12 #define EXE_RESULT_TIMEOUT 1
13 #define EXE_RESULT_MEMORY 2
13 #define EXE_RESULT_MEMORY 2
14 + #define EXE_RESULT_ERROR 3
14
15
15 #ifdef __cplusplus
16 #ifdef __cplusplus
16 extern "C" {
17 extern "C" {
17 #endif
18 #endif
18
19
19 int execute(char *exname, char *inname, char *outname, double t, int max_mem=0);
20 int execute(char *exname, char *inname, char *outname, double t, int max_mem=0);
20
21
21 #ifdef __cplusplus
22 #ifdef __cplusplus
22 }
23 }
23 #endif
24 #endif
24
25
25 #endif
26 #endif
@@ -1,20 +1,20
1 #include <stdio.h>
1 #include <stdio.h>
2 #include <stdlib.h>
2 #include <stdlib.h>
3
3
4 int main()
4 int main()
5 {
5 {
6 int a,b;
6 int a,b;
7 int r;
7 int r;
8 char *huge_array;
8 char *huge_array;
9
9
10 r = scanf("%d %d",&a,&b);
10 r = scanf("%d %d",&a,&b);
11
11
12 - huge_array = (char *)malloc(5000000);
12 + huge_array = (char *)malloc(5*1024*1024);
13 if(huge_array==NULL)
13 if(huge_array==NULL)
14 printf("NO!");
14 printf("NO!");
15 else
15 else
16 printf("%d\n",a+b);
16 printf("%d\n",a+b);
17
17
18 return 0;
18 return 0;
19 }
19 }
20
20
@@ -1,39 +1,56
1 #include <stdio.h>
1 #include <stdio.h>
2 #include <stdlib.h>
2 #include <stdlib.h>
3 #include <unistd.h>
3 #include <unistd.h>
4 - #include <sys/time.h>
5 #include <time.h>
4 #include <time.h>
6 - #include <sys/resource.h>
5 + #include <windows.h>
6 +
7 + // run it for 0.5 s
7
8
8 - // run it for 1.5 s
9 + double get_running_time()
10 + {
11 + FILETIME creation_time;
12 + FILETIME exit_time;
13 + FILETIME kernel_time;
14 + FILETIME user_time;
15 + GetProcessTimes(GetCurrentProcess(),
16 + &creation_time,
17 + &exit_time,
18 + &kernel_time,
19 + &user_time);
20 +
21 + SYSTEMTIME sys_kernel_time;
22 + SYSTEMTIME sys_user_time;
23 +
24 + FileTimeToSystemTime(&kernel_time, &sys_kernel_time);
25 + FileTimeToSystemTime(&user_time, &sys_user_time);
26 +
27 + double time_used =
28 + ((sys_kernel_time.wSecond + sys_kernel_time.wMilliseconds/1000.0) +
29 + (sys_user_time.wSecond + sys_user_time.wMilliseconds/1000.0));
30 + return time_used;
31 + }
9
32
10 int main()
33 int main()
11 {
34 {
12 int a,b;
35 int a,b;
13
36
14 int c=0;
37 int c=0;
15 int r;
38 int r;
16
39
17 r = scanf("%d %d",&a,&b);
40 r = scanf("%d %d",&a,&b);
18 printf("%d\n",a+b);
41 printf("%d\n",a+b);
19
42
20 - struct rusage ru;
21 -
22 while(1) {
43 while(1) {
23 c++;
44 c++;
24 b+=c;
45 b+=c;
25 while(c<100000) {
46 while(c<100000) {
26 c++;
47 c++;
27 b+=c;
48 b+=c;
28 }
49 }
29 - getrusage(RUSAGE_SELF,&ru);
50 + if(get_running_time() > 0.5)
30 - double rtime = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
31 - rtime += (double)ru.ru_utime.tv_usec / 1000000.0;
32 - rtime += (double)ru.ru_stime.tv_usec / 1000000.0;
33 - if(rtime > 0.5)
34 break;
51 break;
35 }
52 }
36 printf("%d\n",b);
53 printf("%d\n",b);
37 exit(0);
54 exit(0);
38 }
55 }
39
56
You need to be logged in to leave comments. Login now