Cheater
Cheater

Reputation: 435

Java Process getting stopped when run in background in linux

I have the below lines of code `

private String build(String command) {
        ShellExecutable obj = new ShellExecutable();
        String output = obj.executeCommand(command);
        return output;
    }

    private String executeCommand(String command) {
        StringBuffer output = new StringBuffer();
        Process p;
        String[] cmdarray = { "bash", "-c", command };
        try {
            System.out.println("Before Command Execution in Bash..& command is: " + command);
            p = Runtime.getRuntime().exec(cmdarray);
            System.out.println("After Command execution in Bash & Before waitFor..");
            p.waitFor();
            System.out.println("After wait for:  " + p.exitValue());
            System.out.println("After wait for:  " + p.isAlive());
            System.out.println("After Command execution in Bash..");
            if (p.getInputStream() != null) {
                System.out.println("Input Stream is present");
                BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    output.append(line + "\n");
                }
            }

            if (p.getErrorStream() != null) {
                System.out.println("Error Stream is present");
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                String errorLine = "";
                while ((errorLine = errorReader.readLine()) != null) {
                    output.append(errorLine + "\n");
                }
            }
        } catch (Exception e) {
            System.out.println("Exception Occured:" + e.getLocalizedMessage() + "Message is:" + e.getMessage());
        }
        return output.toString();
    }

`

I am trying to run this as a foreground process in Linux, it works brilliant. But, when I try to run the same as a background process using nohup the service is stopping. I found similar kind of issues on stack overflow but I couldn't't figure out the solution for this particular case.

For the above code the output I am getting is as follows:

Called listApps...

Before Command Execution in Bash..& command is: xxxxxxxx

After Command execution in Bash & Before waitFor..

[1]+ Stopped nohup java -jar ReadingShell-0.0.1-SNAPSHOT-jar-with-dependencies.jar

I am not getting any exception in the above code, its just stopping without displaying anything. But, when I try displaying p.exitValue() before p.waitFor(), I printed the stacktrace, it is as follows,

java.lang.IllegalThreadStateException: process hasn't exited
at java.lang.UNIXProcess.exitValue(UNIXProcess.java:424)
at org.monitoring.ReadingShell.ShellExecutable.executeCommand(ShellExecutable.java:101)
at org.monitoring.ReadingShell.ShellExecutable.build(ShellExecutable.java:82)
at org.monitoring.ReadingShell.ShellExecutable.getApplicationList(ShellExecutable.java:46)
at spark.RouteImpl$1.handle(RouteImpl.java:72)
at spark.http.matching.Routes.execute(Routes.java:61)
at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:130)
at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1568)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:564)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128)
at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)

Upvotes: 1

Views: 1964

Answers (3)

Tom Chamberlain
Tom Chamberlain

Reputation: 3065

I had a similar issue. The jar file would be fine if ran in the foreground, but stop when executed in nohup with the process/job going into Stopped.

Figured out that nohup will go into stopped if any of the inner scripts try to read from the terminal - see the post here

I used tmux to solve this as suggested by this thread

Upvotes: 0

xenoid
xenoid

Reputation: 8904

You have to read the output streams before you wait for the end of the child process. Otherwise if the child writes more than a buffer's worth (512B? 4K?) to one of the streams, it will be made to wait until something reads and empties the buffer. But this won't happen since your parent process is already executing waitFor().

So, you have to create two threads to read these output streams, and start them before calling waitFor().

Upvotes: 2

jontro
jontro

Reputation: 10628

By reading the opendjk source code for UnixProcess we see the following

public synchronized int waitFor() throws InterruptedException {
    while (!hasExited) {
        wait();
    }
    return exitcode;
}

public synchronized int exitValue() {
    if (!hasExited) {
        throw new IllegalThreadStateException("process hasn't exited");
    }
    return exitcode;
}

hasExited is never reset in the file so logically exitValue() cannot throw after waitFor() is called. (Unless it is interrupted)

Something must be different when you run it than in the code your question has. A minimal complete example class displaying the issue so we can reproduce it would help.

Upvotes: 1

Related Questions