llvm.org GIT mirror llvm / 9ba8a76
Add possibility to set memory limit for binaries run via libSystem. This is especially needed for bugpoint. This partly implements PR688 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34349 91177308-0d34-0410-b5e6-96231b3b80d8 Anton Korobeynikov 12 years ago
16 changed file(s) with 97 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
708708 dnl===-----------------------------------------------------------------------===
709709
710710 AC_CHECK_FUNCS([backtrace ceilf floorf roundf rintf nearbyintf getcwd ])
711 AC_CHECK_FUNCS([getpagesize getrusage gettimeofday isatty mkdtemp mkstemp ])
711 AC_CHECK_FUNCS([getpagesize getrusage getrlimit setrlimit gettimeofday])
712 AC_CHECK_FUNCS([isatty mkdtemp mkstemp ])
712713 AC_CHECK_FUNCS([mktemp realpath sbrk setrlimit strdup strerror strerror_r ])
713714 AC_CHECK_FUNCS([strtoll strtoq sysconf malloc_zone_statistics ])
714715 AC_CHECK_FUNCS([setjmp longjmp sigsetjmp siglongjmp])
122122
123123 /* Define to 1 if you have the `getpagesize' function. */
124124 #undef HAVE_GETPAGESIZE
125
126 /* Define to 1 if you have the `getrlimit' function. */
127 #undef HAVE_GETRLIMIT
125128
126129 /* Define to 1 if you have the `getrusage' function. */
127130 #undef HAVE_GETRUSAGE
7171 ///< expires, the child is killed and this call returns. If zero,
7272 ///< this function will wait until the child finishes or forever if
7373 ///< it doesn't.
74 unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount
75 ///< of memory can be allocated by process. If memory usage will be
76 ///< higher limit, the child is killed and this call returns. If zero -
77 ///< no memory limit.
7478 std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string
7579 ///< instance in which error messages will be returned. If the string
7680 ///< is non-empty upon return an error occurred while invoking the
2828 args.push_back(0);
2929
3030 cerr << "Running 'Graphviz' program... " << std::flush;
31 if (sys::Program::ExecuteAndWait(Graphviz, &args[0],0,0,0,&ErrMsg)) {
31 if (sys::Program::ExecuteAndWait(Graphviz, &args[0],0,0,0,0,&ErrMsg)) {
3232 cerr << "Error viewing graph: " << ErrMsg << "\n";
3333 }
3434 #elif (HAVE_GV && HAVE_DOT)
4848 args.push_back(0);
4949
5050 cerr << "Running 'dot' program... " << std::flush;
51 if (sys::Program::ExecuteAndWait(dot, &args[0],0,0,0,&ErrMsg)) {
51 if (sys::Program::ExecuteAndWait(dot, &args[0],0,0,0,0,&ErrMsg)) {
5252 cerr << "Error viewing graph: '" << ErrMsg << "\n";
5353 } else {
5454 cerr << " done. \n";
6060 args.push_back(0);
6161
6262 ErrMsg.clear();
63 if (sys::Program::ExecuteAndWait(gv, &args[0],0,0,0,&ErrMsg)) {
63 if (sys::Program::ExecuteAndWait(gv, &args[0],0,0,0,0,&ErrMsg)) {
6464 cerr << "Error viewing graph: " << ErrMsg << "\n";
6565 }
6666 }
7373 args.push_back(0);
7474
7575 cerr << "Running 'dotty' program... " << std::flush;
76 if (sys::Program::ExecuteAndWait(dotty, &args[0],0,0,0,&ErrMsg)) {
76 if (sys::Program::ExecuteAndWait(dotty, &args[0],0,0,0,0,&ErrMsg)) {
7777 cerr << "Error viewing graph: " << ErrMsg << "\n";
7878 } else {
7979 #ifdef __MINGW32__ // Dotty spawns another app and doesn't wait until it returns
2020 #include
2121 #if HAVE_SYS_STAT_H
2222 #include
23 #endif
24 #if HAVE_SYS_RESOURCE_H
25 #include
2326 #endif
2427 #if HAVE_SIGNAL_H
2528 #include
105108 Timeout = true;
106109 }
107110
111 static void SetMemoryLimits (unsigned size)
112 {
113 #if HAVE_SYS_RESOURCE_H
114 struct rlimit r;
115 __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
116
117 // Heap size
118 getrlimit (RLIMIT_DATA, &r);
119 r.rlim_cur = limit;
120 setrlimit (RLIMIT_DATA, &r);
121 // Resident set size.
122 getrlimit (RLIMIT_RSS, &r);
123 r.rlim_cur = limit;
124 setrlimit (RLIMIT_RSS, &r);
125 // Virtual memory.
126 getrlimit (RLIMIT_AS, &r);
127 r.rlim_cur = limit;
128 setrlimit (RLIMIT_AS, &r);
129 #endif
130 }
131
108132 int
109133 Program::ExecuteAndWait(const Path& path,
110134 const char** args,
111135 const char** envp,
112136 const Path** redirects,
113137 unsigned secondsToWait,
138 unsigned memoryLimit,
114139 std::string* ErrMsg)
115140 {
116141 if (!path.canExecute()) {
159184 }
160185 }
161186
187 // Set memory limits
188 if (memoryLimit!=0) {
189 SetMemoryLimits(memoryLimit);
190 }
191
162192 // Execute!
163193 if (envp != 0)
164194 execve (path.c_str(), (char** const)args, (char**)envp);
103103 const char** envp,
104104 const Path** redirects,
105105 unsigned secondsToWait,
106 unsigned memoryLimit,
106107 std::string* ErrMsg) {
107108 if (!path.canExecute()) {
108109 if (ErrMsg)
6363 }
6464
6565 BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs,
66 unsigned timeout)
66 unsigned timeout, unsigned memlimit)
6767 : ToolName(toolname), ReferenceOutputFile(OutputFile),
6868 Program(0), Interpreter(0), cbe(0), gcc(0), run_as_child(as_child),
69 run_find_bugs(find_bugs), Timeout(timeout) {}
69 run_find_bugs(find_bugs), Timeout(timeout), MemoryLimit(memlimit) {}
7070
7171
7272 /// ParseInputFile - Given a bytecode or assembly input filename, parse and
4949 bool run_as_child;
5050 bool run_find_bugs;
5151 unsigned Timeout;
52 unsigned MemoryLimit;
5253
5354 // FIXME: sort out public/private distinctions...
5455 friend class ReducePassList;
5657
5758 public:
5859 BugDriver(const char *toolname, bool as_child, bool find_bugs,
59 unsigned timeout);
60 unsigned timeout, unsigned memlimit);
6061
6162 const std::string &getToolName() const { return ToolName; }
6263
262262 InterpreterSel == CBE_bug)
263263 RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
264264 OutputFile, AdditionalLinkerArgs, SharedObjs,
265 Timeout);
265 Timeout, MemoryLimit);
266266 else
267267 RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
268268 OutputFile, std::vector(),
269 SharedObjs, Timeout);
269 SharedObjs, Timeout, MemoryLimit);
270270
271271 if (RetVal == -1) {
272272 std::cerr << "";
193193 prog = sys::Program::FindProgramByName("valgrind");
194194 else
195195 prog = tool;
196 int result = sys::Program::ExecuteAndWait(prog,args,0,0,Timeout,&ErrMsg);
196 int result = sys::Program::ExecuteAndWait(prog, args, 0, 0,
197 Timeout, MemoryLimit, &ErrMsg);
197198
198199 // If we are supposed to delete the bytecode file or if the passes crashed,
199200 // remove it now. This may fail if the file was never created, but that's ok.
3131 const sys::Path &StdInFile,
3232 const sys::Path &StdOutFile,
3333 const sys::Path &StdErrFile,
34 unsigned NumSeconds = 0) {
34 unsigned NumSeconds = 0,
35 unsigned MemoryLimit = 0) {
3536 const sys::Path* redirects[3];
3637 redirects[0] = &StdInFile;
3738 redirects[1] = &StdOutFile;
4546 }
4647
4748 return
48 sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, NumSeconds);
49 sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
50 NumSeconds, MemoryLimit);
4951 }
5052
5153
101103 const std::vector &GCCArgs,
102104 const std::vector &SharedLibs =
103105 std::vector(),
104 unsigned Timeout = 0);
106 unsigned Timeout = 0,
107 unsigned MemoryLimit = 0);
105108 };
106109 }
107110
111114 const std::string &OutputFile,
112115 const std::vector &GCCArgs,
113116 const std::vector &SharedLibs,
114 unsigned Timeout) {
117 unsigned Timeout,
118 unsigned MemoryLimit) {
115119 if (!SharedLibs.empty())
116120 throw ToolExecutionError("LLI currently does not support "
117121 "loading shared libraries.");
141145 );
142146 return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
143147 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
144 Timeout);
148 Timeout, MemoryLimit);
145149 }
146150
147151 // LLI create method - Try to find the LLI executable
208212 const std::string &OutputFile,
209213 const std::vector &ArgsForGCC,
210214 const std::vector &SharedLibs,
211 unsigned Timeout) {
215 unsigned Timeout,
216 unsigned MemoryLimit) {
212217
213218 sys::Path OutputAsmFile;
214219 OutputCode(Bytecode, OutputAsmFile);
219224
220225 // Assuming LLC worked, compile the result with GCC and run it.
221226 return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
222 InputFile, OutputFile, GCCArgs, Timeout);
227 InputFile, OutputFile, GCCArgs,
228 Timeout, MemoryLimit);
223229 }
224230
225231 /// createLLC - Try to find the LLC executable
264270 std::vector(),
265271 const std::vector &SharedLibs =
266272 std::vector(),
267 unsigned Timeout =0 );
273 unsigned Timeout =0,
274 unsigned MemoryLimit =0);
268275 };
269276 }
270277
274281 const std::string &OutputFile,
275282 const std::vector &GCCArgs,
276283 const std::vector &SharedLibs,
277 unsigned Timeout) {
284 unsigned Timeout,
285 unsigned MemoryLimit) {
278286 if (!GCCArgs.empty())
279287 throw ToolExecutionError("JIT does not support GCC Arguments.");
280288 // Construct a vector of parameters, incorporating those from the command-line
305313 DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
306314 return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
307315 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
308 Timeout);
316 Timeout, MemoryLimit);
309317 }
310318
311319 /// createJIT - Try to find the LLI executable
369377 const std::string &OutputFile,
370378 const std::vector &ArgsForGCC,
371379 const std::vector &SharedLibs,
372 unsigned Timeout) {
380 unsigned Timeout,
381 unsigned MemoryLimit) {
373382 sys::Path OutputCFile;
374383 OutputCode(Bytecode, OutputCFile);
375384
378387 std::vector GCCArgs(ArgsForGCC);
379388 GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
380389 return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
381 InputFile, OutputFile, GCCArgs, Timeout);
390 InputFile, OutputFile, GCCArgs,
391 Timeout, MemoryLimit);
382392 }
383393
384394 /// createCBE - Try to find the 'llc' executable
411421 const std::string &InputFile,
412422 const std::string &OutputFile,
413423 const std::vector &ArgsForGCC,
414 unsigned Timeout ) {
424 unsigned Timeout,
425 unsigned MemoryLimit) {
415426 std::vector GCCArgs;
416427
417428 GCCArgs.push_back(GCCPath.c_str());
487498 FileRemover OutputBinaryRemover(OutputBinary);
488499 return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
489500 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
490 Timeout);
501 Timeout, MemoryLimit);
491502 }
492503
493504 int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
6363 const std::string &OutputFile,
6464 const std::vector &GCCArgs =
6565 std::vector(),
66 unsigned Timeout = 0);
66 unsigned Timeout = 0,
67 unsigned MemoryLimit = 0);
6768
6869 /// MakeSharedObject - This compiles the specified file (which is either a .c
6970 /// file or a .s file) into a shared object.
123124 std::vector(),
124125 const std::vector &SharedLibs =
125126 std::vector(),
126 unsigned Timeout = 0) = 0;
127 unsigned Timeout = 0,
128 unsigned MemoryLimit = 0) = 0;
127129 };
128130
129131 //===---------------------------------------------------------------------===//
155157 std::vector(),
156158 const std::vector &SharedLibs =
157159 std::vector(),
158 unsigned Timeout = 0);
160 unsigned Timeout = 0,
161 unsigned MemoryLimit = 0);
159162
160163 /// OutputCode - Compile the specified program from bytecode to code
161164 /// understood by the GCC driver (either C or asm). If the code generator
195198 std::vector(),
196199 const std::vector &SharedLibs =
197200 std::vector(),
198 unsigned Timeout = 0);
201 unsigned Timeout = 0,
202 unsigned MemoryLimit = 0);
199203
200204 virtual GCC::FileType OutputCode(const std::string &Bytecode,
201205 sys::Path &OutFile);
4545 cl::desc("Number of seconds program is allowed to run before it "
4646 "is killed (default is 300s), 0 disables timeout"));
4747
48 static cl::opt
49 MemoryLimit("mlimit", cl::init(100), cl::value_desc("MBytes"),
50 cl::desc("Maximum amount of memory to use. 0 disables check."));
51
4852 // The AnalysesList is automatically populated with registered Passes by the
4953 // PassNameParser.
5054 //
6771 sys::PrintStackTraceOnErrorSignal();
6872 sys::SetInterruptFunction(BugpointInterruptFunction);
6973
70 BugDriver D(argv[0],AsChild,FindBugs,TimeoutValue);
74 BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit);
7175 if (D.addSources(InputFilenames)) return 1;
7276 D.addPasses(PassList.begin(), PassList.end());
7377
243243 args.push_back(InputFilename.c_str());
244244 args.push_back(0);
245245
246 return sys::Program::ExecuteAndWait(llc,&args[0],0,0,0,&ErrMsg);
246 return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg);
247247 }
248248
249249 /// GenerateCFile - generates a C source file from the specified bytecode file.
260260 args.push_back(OutputFile.c_str());
261261 args.push_back(InputFile.c_str());
262262 args.push_back(0);
263 return sys::Program::ExecuteAndWait(llc, &args[0],0,0,0,&ErrMsg);
263 return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg);
264264 }
265265
266266 /// GenerateNative - generates a native object file from the
341341
342342 // Run the compiler to assembly and link together the program.
343343 int R = sys::Program::ExecuteAndWait(
344 gcc, &args[0], (const char**)clean_env,0,0,&ErrMsg);
344 gcc, &args[0], (const char**)clean_env, 0, 0, 0, &ErrMsg);
345345 delete [] clean_env;
346346 return R;
347347 }
515515 args[1] = RealBytecodeOutput.c_str();
516516 args[2] = tmp_output.c_str();
517517 args[3] = 0;
518 if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0, &ErrMsg)) {
518 if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0,0, &ErrMsg)) {
519519 if (tmp_output.isBytecodeFile()) {
520520 sys::Path target(RealBytecodeOutput);
521521 target.eraseFromDisk();
498498 Timer timer(action->program.toString());
499499 timer.startTimer();
500500 int resultCode =
501 sys::Program::ExecuteAndWait(action->program, Args,0,0,0,&ErrMsg);
501 sys::Program::ExecuteAndWait(action->program, Args,0,0,0,0, &ErrMsg);
502502 timer.stopTimer();
503503 timer.print(timer,std::cerr);
504504 return resultCode;
505505 }
506506 else
507507 return
508 sys::Program::ExecuteAndWait(action->program, Args, 0,0,0, &ErrMsg);
508 sys::Program::ExecuteAndWait(action->program, Args, 0,0,0,0, &ErrMsg);
509509 }
510510 return 0;
511511 }
457457 args.push_back(tmpAsmFilePath.c_str());
458458 args.push_back(0);
459459
460 if (sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 1, &ErrMsg)) {
460 if (sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 1, 0, &ErrMsg)) {
461461 cerr << "lto: " << ErrMsg << "\n";
462462 return LTO_ASM_FAILURE;
463463 }