4

In my c++ program I am going to start other programs. If those programs use over a certain amount of memory, I want my program to kill their processes. How can that be done?

I will probably use execv to start the programs.

node ninja
  • 31,796
  • 59
  • 166
  • 254

3 Answers3

8

Assuming, you're on a POSIX system, you can limit this by calling setrlimit(2) after fork(). For example:

if (fork() == 0) {
    struct rlimit limits;
    limits.rlim_cur = 10000000; // set data segment limit to 10MB
    limits.rlim_max = 10000000; // make sure the child can't increase it again
    setrlimit(RLIMIT_DATA, &limits);
    execv(...);
}

If your child process attempts to allocate more memory than this, it won't be killed automatically, but it will fail to satisfy memory allocation requests. If the child program chooses to abort in this situation, then it will die. If it chooses to continue, the parent won't be notified of this situation.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • You can just use an integer for the `const struct rlimit*` second parameter? – Mike DeSimone Apr 26 '11 at 00:17
  • +1 for being more complete (and thus more useful) than my answer. – Robᵩ Apr 26 '11 at 00:19
  • Before this code, how do I start the program? Does the program get started at the end? – node ninja Apr 26 '11 at 03:12
  • Right, you use `execv()` or whatever in the normal way to start the child process. The key to remember is to set the limit *after* the `fork()` and *before* the `exec()`. – Greg Hewgill Apr 26 '11 at 03:14
  • What if I want to add in another thing to consider: time. Like say, I want to limit how long programs can use over 10MB of memory. Can this be modified to do that? – node ninja Apr 28 '11 at 04:13
  • @z-buffer: No, not directly. The `setrlimit()` facility itself does not have the concept of time (except for `RLIMIT_CPU`, which limits the total amount of CPU time the process can use). – Greg Hewgill Apr 28 '11 at 04:19
5

Read up on the setrlimit function. You probably want something like:

#include <sys/resource.h>

struct rlimit limits;
limits.rlim_cur = // soft limit
limits.rlim_max = // hard limit
int err = setrlimit(RLIMIT_DATA, &limits);
if(err) ...

This assumes you're writing for Unix/Linux/BSD/Mac/etc., not Windows... which seems like a good guess since you're using execv.

A couple notes: the soft limit (rlim_cur) may notify the process that the limit is exceeded. Exceeding the hard limit (rlim_max) makes malloc() fail, setting errno to ENOMEM, which usually leads to the process dying. Read the man page or try it out to see how it works on your system. If the stack outgrows rlim_max, you may get a SIGSEGV signal.

Generally, only a root process can raise rlim_max. A regular process can lower rlim_max or set rlim_cur to anything in the range between 0 and rlim_max.

Mike DeSimone
  • 41,631
  • 10
  • 72
  • 96
4

In Linux, you probably want to use setrlimit. Don't bother killing the children, though. When they run out of memory, they'll die on their own.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308