Description:
added box for windows
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r98:e2e8e4763e22 - - 5 files changed: 479 inserted, 0 deleted

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