Gradle does not gracefully handle test exits

To avoid overly long test times, tests will fail when a certain deadline has been met (mostly 3000 seconds, but configurable by the tests). This is done by simply killing the test process with a System.exit(37).

This is what happens when the gradle test executor ‘detects’ this behavior:

… SEVERE: Deadline (3000 seconds) passed for unit test UniqueKeyTest.testMaintainUniqueKeysPrivilege, killing process. Process ‘Gradle Worker 4’ finished with exit value 37 (state: FAILED) Unexpected exception thrown. org.gradle.messaging.remote.internal.MessageIOException: Could not read message from ‘/0:0:0:0:0:0:0:1:33878’.

at org.gradle.messaging.remote.internal.inet.SocketConnection.receive(SocketConnection.java:88)

at org.gradle.messaging.remote.internal.hub.MessageHub$ConnectionReceive.run(MessageHub.java:230)

at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)

at java.lang.Thread.run(Thread.java:722) Caused by: com.esotericsoftware.kryo.KryoException: Buffer underflow.

at com.esotericsoftware.kryo.io.Input.require(Input.java:162)

at com.esotericsoftware.kryo.io.Input.readByte(Input.java:255)

at org.gradle.messaging.remote.internal.hub.InterHubMessageSerializer$MessageReader.read(InterHubMessageSerializer.java:64)

at org.gradle.messaging.remote.internal.hub.InterHubMessageSerializer$MessageReader.read(InterHubMessageSerializer.java:53)

at org.gradle.messaging.remote.internal.inet.SocketConnection.receive(SocketConnection.java:83)

… 5 more

1 Like

Hi Jesper, I’m not sure I follow this, is the test itself calling System.exit(), or are you saying Gradle is calling System.exit()? A sample unit test would be useful in understanding your problem. Typically, calling System.exit() is a bad practice as it exits the current JVM and I’m not sure that’s what you want to do. An alternative would be to use the java.util.concurrent libraries or Netflix’s Hystrix library (https://github.com/Netflix/Hystrix) to isolate the execution in a separate thread.

Thanks, topher

Instead of ‘System.exit’, the tests should use ‘@Timeout’ or a similar facility provided by your test framework of choice

Thanks for your suggestions, I agree that the System.exit is a bad thing, but that’s just how our 4000+ tests work at the moment. We’ll try to find a way around it.

I recommend to search the codebase for ‘System.exit’ and to refactor affected methods. This may take some work, but it’s definitely worth it.

The only workaround I can think of is to install a security manager/policy that forbids use of ‘System.exit’ in test JVMs. This will make tests fail with a ‘SecurityException’, which will be treated as a regular test failure. I’ve never tried this though, so I can’t tell if it is going to work in practice. Also, I’d rather fix the cause than the symptom.