1

I'm writing a Java program with multiple threads. One of the threads is responsible for reading lines from the standard input and parsing them.

Everything works well when running normally, but when the program is run in the background (in Linux) using:

$ java -jar my_jar_file &

my program hangs (at least until brought to foreground).

When running in the background I don't really need the standard input, but I also don't want my program to hang.

I searched for a way to programatically determine if the process is running in the background but could not find it.

Here's the code that reads from standard input:

InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(inputStreamReader);

String line = null;

try {
  while ((line = br.readLine()) != null) {
    parseInputLine(line, br);
  }
} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

As far as I can tell, the program hangs when it reaches the br.readLine() command.

Ari
  • 21
  • 4
  • 3
    It does not make sense to read from stdin when you run program in background. – Leos Literak Aug 22 '13 at 15:09
  • Yeah, standard I/O blocks for certain read/write operations. If you want it to be non-blocking, you should use NIO. – Josh M Aug 22 '13 at 15:13
  • I completely agree, that is why I'm trying to find a way to detect that I am running in the background and then not even try to read from STDIN – Ari Aug 22 '13 at 15:14
  • Josh - What is "NIO"? – Ari Aug 22 '13 at 15:15
  • @Ari new input/output. An article comparing the 2 can be found [here](http://java.dzone.com/articles/java-nio-vs-io) – Josh M Aug 22 '13 at 15:17
  • @Ari What is the real problem? One of your comments below indicates you want to know why your application hangs when in the background. That's different than what you asked. If you have other threads that you think should be running (and that's what you're trying to solve), we need to see more code: this is likely a concurrency issue and not a I/O one. – wolfcastle Aug 22 '13 at 15:52
  • @wolfcastle - I apologize if I wasn't clear enough. I just want my application not to hang when running in the background either by detecting that it is in the background (this would be the ideal solution for me) or by changing the code I posted above so that the application does not hang. Posting the entire code is a bit hard since it's a very large one including a GUI... – Ari Aug 22 '13 at 16:03
  • What do you want to have happen when the background task's thread reads from stdin? Maybe you want to read from `/dev/null` to it to cause an immediate EOF? – Jim Garrison Aug 22 '13 at 16:31
  • @JimGarrison - that would work, then that specific thread would end and the rest of them would continue working. How can that be achieved? – Ari Aug 22 '13 at 16:59

4 Answers4

0

I would guess the reader is blocking waiting for input you might be able to pipe in your input from the command line

dkatzel
  • 31,188
  • 3
  • 63
  • 67
  • 1
    The question is why this is blocking the entire program and not letting other threads run normally (it works fine when the process is in foreground). – Ari Aug 22 '13 at 15:13
0

readLine is a blocking call. So it is obviously waiting for input. If you want it to run in the background, then pass to it input from a file like this

java TakeInput < test.txt &

This where the class is as below and test.txt also shown below:

public class TakeInput
{
    public static void main(String[] args)
    {
        InputStreamReader inputStreamReader = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(inputStreamReader);

        String line = null;

        try {
          while ((line = br.readLine()) != null) {
              System.out.println(line);
          }
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
    }
}

write a text file as test.txt which has say

test1
test2
test3
Raji
  • 527
  • 3
  • 6
  • 1
    I am aware that readLine is blocking, that is why I have a dedicated thread for it. The problem I am trying to understand is why other (completely unrelated) threads hang when running in the background (everything works fine when in foreground) – Ari Aug 22 '13 at 16:04
  • Take a look at this... http://stackoverflow.com/questions/285015/linux-prevent-a-background-process-from-being-stopped-after-closing-ssh-client – Raji Aug 23 '13 at 03:52
  • using `<$-` does the trick (i.e. my program is able to run in the background without getting stuck) but it still means I need to explicitly "help" it understand that it runs in the background by changing the command (same as using `< /dev/null`). What I am really looking for is a way to do it automatically. – Ari Aug 23 '13 at 06:12
0

I don't believe a Java program can determine if it's running in foreground or background.

I tried System.console(), with the following results:

  • Linux - returns null if stdin is redirected from a file, independent of foreground/background status
  • Windows - same thing;
  • Cygwin - seems to always return null

I suspect you will need to invoke the program from the command line as

java -cp ... ClassName < /dev/null
Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
0

Try using .ready() function.

try {
      if (stdError.ready()) 
      {
            while((line= stdError.readLine()) != null){
                logger.error(line);
            }
      }
}

Do the same for the stdout.