RFR: 8359827: Test runtime/Thread/ThreadCountLimit.java should run exclusively [v3]
SendaoYan
syan at openjdk.org
Wed Jul 23 02:36:36 UTC 2025
On Tue, 22 Jul 2025 21:41:44 GMT, David Holmes <dholmes at openjdk.org> wrote:
>>> If the ulimit setting only affects the sub-shell then it can't cause other concurrent tests to hit the limit and fail to create threads!
>>
>> Maybe some of my previous statements have caused some misunderstandings.
>> The usage of ulimit in this testcase will not cause other concurrent tests to hit the limit, but will cause this test itself do not have enough user processes to start the java.
>> On the huge core number machine, every test will create more JIT compiler threads and more GC work threads. So when this test run with other tests simultancely, we can see this test can not start subprocess java with prefix "ulimit -u", the subprocess java report `Failed to start thread "GC Thread#0"`, because the subprocess has limited by "ulimit -u 4096", and the user processes resources maybe has been occupied by other tests which run simultancely. And the other tests run normally, because they do not have 'ulimit -u' explicitly.
>
>> The usage of ulimit in this testcase will not cause other concurrent tests to hit the limit, but will cause this test itself do not have enough user processes to start the java.
>
> Sorry - right I get it now. So basically with enough other activity on the machine all the 4096 process/thread capacity may have already been used up before the test can run. It isn't this test that is the "resource hog" as such. What we really want to do is more like `ulimit -u <current process/thread count> + 4096` but getting the current value is tricky.
>
> One possible solution would be to loop so that if we get exitcode 1 then we retry with 4096*2 etc.
>
> if (Platform.isLinux()) {
> // On Linux this test sometimes hits the limit for the maximum number of memory mappings,
> // which leads to various other failure modes. Run this test with a limit on how many
> // threads the process is allowed to create, so we hit that limit first. What we want is
> // for another "limit" processes to be available, but ulimit doesn't work that way and
> // if there are already many running processes we could fail to even start the JVM properly.
> // So we loop increasing the limit until we get a successful run. This is not foolproof.
> int pLimit = 4096;
> final String ULIMIT_CMD = "ulimit -u ";
> ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(ThreadCountLimit.class.getName());
> String javaCmd = ProcessTools.getCommandLine(pb);
> for (int i = 1; i <= 10; i++) {
> // Relaunch the test with args.length > 0, and the ulimit set
> String cmd = ULIMIT_CMD + Integer.toString(pLimit * i) + " && " + javaCmd + " dummy";
> System.out.println("Trying: bash -c " + cmd);
> OutputAnalyzer oa = ProcessTools.executeCommand("bash", "-c", cmd);
> int exitValue = oa.getExitValue();
> switch (exitValue) {
> case 0: System.out.println("Success!"); return;
> case 1: System.out.println("Retry ..."); continue;
> default: oa.shouldHaveExitValue(0); // generate error report
> }
> }
> throw new Error("Failed to perform a successful run!");
> } else {
> // Not Linux so run directly.
> test();
> }
>
> Took 5 loops to run on my system (ulimit -u 24576) when I had an unrestricted version of the test running which has about 20700 live threads.
Thanks @dholmes-ora very much.
I will verified this patch by ours CI.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/26401#issuecomment-3105457139
More information about the hotspot-runtime-dev
mailing list