I have a very strange situation where a Java process seems to hang when called via Apache/PHP, but OK when invoked from the command line. I spent hours debugging this, no avail. Any and all thoughts welcome!
Situation: I have a .class file (without the original Java code) that reads an input file, processes the read information, and writes a report on stdout. The Java code doesn’t read stdin, and only writes stdout. I wrapped this in a tiny Perl script that basically just execs “java -cp /path/to/classfile MyJavaProgram /path/to/inputfile/to/process”. That way I can invoke it from the command line for testing, this works like a charm. Next, I try to invoke this from PHP using popen(), and there Java just hangs. I see the Perl process in the ps list, and Java; but the Java process waits forever. Once I kill it, the webserver page continues loading (but of course without the expected output that the Java process would generate).
What I tried so far:
- Wrapping the Java process in a shell script, same behaviour. Java just hangs.
- Running it from PHP with popen() without a wrapper, same behaviour.
- Starting it from PHP with system() or passthru(), same behaviour.
- In the Perl wrapper, reopening STDIN for /dev/null (so that reading stdin immediately returns EOF), same behaviour.
- In the Perl wrapper, reopening STDERR for /dev/null, same behaviour.
- In the Perl wrapper, reopening STDOUT for /dev/null. Here I would expect no output (as it gets discarded) but still the Java process just hangs.
- In the Perl wrapper, reopening all 3 streams for /dev/null. Java still hangs.
- Replacing the Java invocation in the Perl wrapper with a simple “ls -l /bin”. This works as expected; the web page gets populated with the “ls” listing. So the problem isn’t in PHP or Perl.
- Starting the Java process with a “/bin/sh -c ‘java …..'”. Same behaviour, Java hangs.
- In the Perl wrapper, I dump the environment variables too, to check them. Environment seems OK.
- When the Java process is running, I look up the Perl wrapper invocation in the ps list, and copy/paste it to the command line. Works like a charm.
- Similarly, when the Java process is hanging, I look up the invocation in the ps list, and copy/paste it to the command line. Works like a charm.
- I also verified that the the input file is readable when invoked from the web server. All above tests with the command line were run using the same user ID as the Apache user.
Unfortunately I can’t replace the Java code with something that’s under my control. I only have the .class file to work with. What I haven’t tried yet is to run this under Linux, so this still might be an OSX specific issue (which would surprise me).
What the hell is going on here? Any and all “wild” ideas appreciated.. thanks!
Check ALL environment from apache AND from cmd line, including the paths, UIDs etc.
Also check what the java process does when hanging (use truss/tusc/strace -f java xxxxxxxxxxx 2>/tmp/trace.$$ ) when wrapping it from both places (apache and cmdline), then compare the results.
Also, when wrapping from perl, set autoflush to 1 for stdin, stdout, stderr before exec-ing java.