Search code examples
javalinuxbashbackground-process

Java program continues to run (in background) even after last statement in main


Background

I am having a simple java program which reads data from std input. I am executing it though from a bash script executer.sh

python2 readLines.py | tee logfile |  java MsgReader

readLines.py reads data from a file line by line and throws it on the stdout

MsgReader.java

import kafka.javaapi.producer.Producer;

public void process() {
    String msg = ""; 
    BufferedReader stdinReader = new BufferedReader(new InputStreamReader(System.in)

    Producer producer = new Producer();//it takes config file as parameter which is not related to the question here

    try {
         while ((msg = stdinReader.readLine()) != null) {
              producer.send(message);
         }   
         stdinReader.close();
     } catch (IOException|FailedToSendMessageException e) {
            System.out.println("Send message failed!");
            e.printStackTrace();
     }   
}   

public static void main(String args[]) throws JSONException,IOException {
    try{
        Date now = new Date();
        System.out.println("Start : " + now);
        process();// Continuously reads logs
        now = new Date();
        System.out.println("After : " + now);
    } catch(Exception e){ 
        e.printStackTrace();
        return;
    }   
}   

Execution

./executer.sh & : executing in the background

Problem

After reading all the lines readLines.py ends, but executer.sh and MsgReader.java are stll executing as verified by ps command. The statement System.out.println("After : " + now); os recorded in the log file, indicating the program has reached the last statement in the main function.

How to terminate the java program and bash script gracefully.

I do not want to add System.exit() here.

Platform

CentOS release 6.7 (Final)

java 1.7.0_95

python 2.7.6


Solution

  • You did not close the Producer. From the Javadoc for KafkaProducer (the implementation of Producer):

    The producer consists of a pool of buffer space that holds records that haven't yet been transmitted to the server as well as a background I/O thread that is responsible for turning these records into requests and transmitting them to the cluster. Failure to close the producer after use will leak these resources.

    The background thread is still running and will prevent the process from ending until you close the Producer, preferably in a finally block after the try/catch. Also, that stdinReader.close(); belongs in the finally as well.