1

I want to limit the memory usage of a child process using rlimit. Currently our code is as follows:

old_rlimit := get_rlimit()
set_rlimit(child_process_rlimit)
cmd.Start()
set_rlimit(old_rlimit)
cmd.Wait()

However, sometimes Golang runtime will report out of memory error at cmd.Start(). It seems that in cmd.Start() current process will allocate some memory, and if current memory usage is higher than child_process_rlimit, an error will be raised.

I want to know is there any way to limit the memory usage of child process without affecting current one?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
lz96
  • 2,816
  • 2
  • 28
  • 46

1 Answers1

0

You need to apply rlimit to the child process only rather than relying on rlimit inheritance. Your main blocker here is clearly spelled out in the setrlimit man page:

an unprivileged process may set only its soft limit to a value in the range from 0 up to the hard limit, and (irreversibly) lower its hard limit

The standard way to do this is through fork/exec, something along the lines of:

child_pid := fork()
if pid != 0 {
  // in child process
  setrlimit(...)
  execve(...)
}

If you don't want to do that, you still have a few options:

  • run as privileged user
  • cmd.Run a small wrapper (eg: bash ulimit -m ...) that calls the child process. note: -m is not honored by many systems.
  • call prlimit (linux-specific and no syscall wrapper. see this thread for details)
Marc
  • 19,394
  • 6
  • 47
  • 51
  • What if the address space of the new rlimit is lower than current usage? Will the subsequent `execve` fail in this case? – lz96 Jan 17 '18 at 08:16
  • 1
    Depending on which limit you're setting, you may get killed first, or `execve` may fail. Also be aware that I have no idea what is necessary to run `fork/exec` manually in Go (you may want to dig through the `os/exec` code. – Marc Jan 17 '18 at 08:26