Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to child process created using JavaExec in Gradle

Tags:

gradle

groovy

I have a Gradle task that invokes a Java process using a task of type JavaExec. It looks something like this -

task runScript (dependsOn: 'classes', type: JavaExec) {
    main = 'org.my.package.MyClass'
    classpath = sourceSets.main.runtimeClasspath
}

It works great except that I don't know how I can get a reference to the child process created this way.

I want to register a shutdown hook in my Gradle script and call shutdown on child processes created by my Gradle script. Is there a way to achieve this?

The problem I am having is that if I kill the Gradle process (using ctrl+c). Gradle itself dies but the child processes that are spawned using Gradle task live on. I would like the ability to invoke shutdown on the child process if my Gradle process catches a kill signal.

like image 899
neesh Avatar asked Oct 30 '25 09:10

neesh


1 Answers

Seems to work for me... If I use the following gradle script:

apply plugin: "java"

repositories {
    mavenCentral()
}

dependencies {
}

task runScript(dependsOn: 'classes', type: JavaExec) {
    main = 'test.Main'
    classpath = sourceSets.main.runtimeClasspath
}

Then in src/main/java/test I put the following in Main.java (Java 8)

package test;

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("FINISHING")));
        new ScheduledThreadPoolExecutor(1).scheduleAtFixedRate(() -> System.out.println("PING"), 0, 1, TimeUnit.SECONDS);
    }
}

Then (with Gradle 2.12), if I run the runScript task, I see the output:

$ gradle runScript
:compileJava
:processResources UP-TO-DATE
:classes
:runScript
PING
PING
PING

Then, when I press CTRL-C, it prints:

> FINISHING
[0m> Building 75% > :runScript
$

And stops...

So the shutdown hook is called...

Is this what you're seeing?


So, to test it with a Groovy Class, I changed the above build.gradle to:

apply plugin: "groovy"

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.6'
}

task runScript(dependsOn: 'classes', type: JavaExec) {
    main = 'test.Main'
    classpath = sourceSets.main.runtimeClasspath
}

task gRunScript(dependsOn: 'classes', type: JavaExec) {
    main = 'test.GMain'
    classpath = sourceSets.main.runtimeClasspath
}

Then added a Groovy class (in src/main/groovy/test/GMain.groovy)

package test

import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.TimeUnit

class GMain {
    static main(args) {
        Runtime.runtime.addShutdownHook(new Thread({ -> println 'GFINISHING' }))
        new ScheduledThreadPoolExecutor(1).scheduleAtFixedRate({ -> println "GPING"}, 0, 1, TimeUnit.SECONDS)
    }
}

And running gRunScript (instead of runScript) gave me the output:

$ gradle gRunScript
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:gRunScript
GPING
GPING
> GFINISHING
> Building 80% > :gRunScript

And stops...

So the shutdown hook is called...

like image 107
tim_yates Avatar answered Nov 02 '25 11:11

tim_yates