docker run --ulimit cpu=10 does not kill java proc

2019-05-29 01:18发布

问题:

I want to make sure the process gets killed after 10 seconds of CPU time. Docker run command accepts the flag --ulimit cpu=10 that is supposed to do that.

However when I run java command using this, the ulimit setting is ignored. The java process with infinite loop continues even after 10s (actually for minutes until I kill it) Here is the command I used to test.

docker run --rm -i -v /usr/local/src:/classes --ulimit cpu=10 java:8 \
java -cp /classes/ InfiniteLoop

Instead of invoking java directly, if I start bash and then run java c, it works as expected.

docker run --rm -i -v /usr/local/src:/classes --ulimit cpu=10 java:8 \
bash -c 'date; java -cp /classes/ InfiniteLoop'

Why does invoking java program directly does not respect ulimit option?

Edit 1:

$ docker --version
Docker version 1.9.1, build a34a1d5

The java program is, InfiniteLoop.java

import java.util.*;

class InfiniteLoop {
  public static void main(String[] args) throws Exception {
    for (long i = 0; i < 1000_000_000_000L; i++) {
      if (i % 1_000_000_000 == 0) {
        System.out.println(new Date() + ", i = " + i);
      }
    }
  }
}

Edit 2: The following doesn't work either. That is, with only java executed in the bash.

docker run --rm -i -v /usr/local/src:/classes --ulimit cpu=10 java:8 \
bash -c 'java -cp /classes/ InfiniteLoop'

But, adding any noop or ':' command works. Or even an arbitrary word that prints "command not found" also works.

docker run --rm -i -v /usr/local/src:/classes --ulimit cpu=10 java:8 \
bash -c ':; java -cp /classes/ InfiniteLoop'

and this works too.

docker run --rm -i -v /usr/local/src:/classes --ulimit cpu=10 java:8 \
bash -c 'ArbirtraryCommandNotFound; java -cp /classes/ InfiniteLoop'

Edit 3: Similar to using the no-op (:), invoking the process with time also makes the process to be killed exactly after the CPU time is exceeded.

docker run --rm -i -v /usr/local/src:/classes --ulimit cpu=10 java:8 \
bash -c 'time java -cp /classes/ InfiniteLoop'

回答1:

After some experimenting I re-read the original question and also took into account the fact that it is independent of the type of program being launched, that is, Java, C++, etc.: the reason why it works in the one case (when invoked with bash -c) and not when you directly invoke it is that ulimit is a bash built in command and the docs for docker run are not entirely transparent about it.