K Erlandsson K Erlandsson - 4 months ago 12
Ruby Question

Ruby script that sets environment variable fails with Invalid argument - ruby_setenv (Errno::EINVAL) when started from a Java process on Windows

I have a very simple ruby script that looks like this:

puts "Running test program"
ENV["TEST"] = "foo"
puts ENV["TEST"]


When I run this script from the command line it works as expected:

C:\Temp\rb-test>ruby foo.rb
Running test program
foo


What I need to do is to launch this script from a Java program. The Java program looks like this:

Path path = FileSystems.getDefault().getPath("c:", "temp", "rb-test");
ProcessBuilder pb = new ProcessBuilder("ruby.exe", "foo.rb").directory(path.toFile()).redirectErrorStream(true);
Process process = pb.start();
process.waitFor();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = bufferedReader.readLine();
while (line != null) {
System.out.println(line);
line = bufferedReader.readLine();
}


When I run the Java program from Eclipse I get the following output:

foo.rb:2:in `[]=': Invalid argument - ruby_setenv (Errno::EINVAL)
from foo.rb:2:in `<main>'
Running test program


In reality I am calling a larger Ruby script from a third party product (Vagrant), why changing the Ruby script is not an option.

Why is this happening? Can I get around it by modifying my Java code somehow?

Ruby version:
ruby 1.9.3p0 (2011-10-30) [i386-mingw32]


Update: The java code actually works if I run it from a cmd window. It does not work when I run it from within Eclipse. Unfortunately this does not help much since I am working on a tool we will run from within Eclipse.

Update 2: If I start a cmd window from Eclipse, I get the same problem when I run the ruby script from within this cmd window. This leads me to believe there is some kind of permission issue. However, I cannot see any permission differences between the cmd I start through the start menu and the one started through Eclipse. Both are run as the same user and all security properties I can see for the process are identical.

Update 3: Tried the latest version of Ruby (
2.0.0p247 (2013-06-27) [i386-mingw32]
). Same behavior.

Answer

The problem was that when I started the Ruby script from Eclipse I had a different environment. Specifically, I had a CLASSPATH environment variable that looked really strange. I think the cause of this is the size of the CLASSPATH variable. It is really really long before being passed on to my sub process but within the sub process it is truncated and looks broken.

I am suspecting I am running into problems with the max size of the Windows environment block (see details here: http://blogs.msdn.com/b/oldnewthing/archive/2010/02/03/9957320.aspx). I will not investigate this further but have fixed my code to remove the CLASSPATH variable before starting the process.

Path path = FileSystems.getDefault().getPath("c:", "temp", "rb-test");
ProcessBuilder pb = new ProcessBuilder("ruby.exe","foo.rb").directory(path.toFile()).redirectErrorStream(true);
pb.environment().remove("CLASSPATH");
Process process = pb.start();
process.waitFor();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = bufferedReader.readLine();
while (line != null) {
    System.out.println(line);
    line = bufferedReader.readLine();
}