Exec task hangs, process spammed with SIGTTIN (Linux, Gradle 2.14)


(Adrien) #1

Hi,

I’m using Gradle 2.14 on Linux, and want to use an Exec task to run a python script that uses the Sage ( http://www.sagemath.org/ ). The python script would usually be run invoking the sage command:

sage -python myscript.py

A reduced test case demonstrating the issue is:

  • build.gradle
task hang(type: Exec) {
    commandLine "sage", "-python", "hello.py"
}
  • hello.py (to put next to build.gradle)
print('Hello world')

with this setup, running gradle hang will make Gradle, well, hang :slight_smile: It looks like there is some weird TTY signal magic going on, as running top will show both the java and the sage processes hogging 100% CPU. Attaching strace to any of them shows that they get spammed by SIGTTIN signals, which I suspected had to do with redirection of stdin or any other stream.

I then tried the following java code:

import java.io.File;
import java.util.Arrays;
import java.util.List;

public class Main {
	public static void run() throws Exception {
		final ProcessBuilder pb = new ProcessBuilder();
		final List<String> cmd = Arrays.asList("sage", "-python", "hello.py");
		pb.command(cmd);
		pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
		pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
		pb.redirectError(ProcessBuilder.Redirect.INHERIT);
		final Process proc = pb.start();
		System.out.println("Exit code: " + proc.waitFor());
	}

	public static void main(String[] args) {
		try {
			run();
		} catch (Exception e) {
			System.err.println(e.toString());
		}
	}
}

the following code runs the program succesfully, printing “Hello world” and then “Exit code: 0” on stdout. So it does not seem to be an issue with ProcessBuilder itself. My next attempt was to define a hang2 task to check that the issue was not related to Gradle’s way of executing things, which I did like this:

import java.io.File;
import java.util.Arrays;
import java.util.List;

task hang2 << {
	final ProcessBuilder pb = new ProcessBuilder();
	final List<String> cmd = Arrays.asList("sage", "-python", "hello.py");
	pb.command(cmd);
	pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
	pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
	pb.redirectError(ProcessBuilder.Redirect.INHERIT);
	final Process proc = pb.start();
	System.out.println("Exit code: " + proc.waitFor());
}

but this hangs as the normal hang task. So somehow Gradle seems to (only suspecting here) change the environment in which the sage process is run, which makes both process hang, and I really don’t understand what’s going on. Any support is appreciated :slight_smile:

For the record, the strace lines look like this:

--- SIGTTIN {si_signo=SIGTTIN, si_code=SI_USER, si_pid=20970, si_uid=1000} ---

Gradle version information:

------------------------------------------------------------
Gradle 2.14
------------------------------------------------------------

Build time:   2016-06-14 07:16:37 UTC
Revision:     cba5fea19f1e0c6a00cc904828a6ec4e11739abc

Groovy:       2.4.4
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_92 (Oracle Corporation 25.92-b14)
OS:           Linux 4.5.7-200.fc23.x86_64 amd64

This is not a regression


(Adrien) #2

I found the root cause of the issue: the sage “binary” is a shell script, and its shebang calls bash explicitly passing the -i (interactive shell) flag, which seems to make things go wrong afterwards. Not invoking sage directly but the equivalent of bash $(which sage) from Gradle makes things work. I’m still puzzled as for why this only happens in Gradle, and not in a normal Java program.