Paul Erlenmeyer
Paul Erlenmeyer

Reputation: 521

BufferedReader Deadlock: How to properly shutdown a BufferedReader

I have a deadlock problem with a BufferedReader that reads from an InputStreamReader (that reads from an InputStream).

There is a Swing GUI that is beeing closed by the user. The JFrame is beeing disposed and a finish Method is invoked.

 DppGUI gui = this;
 addWindowListener(new WindowAdapter()
    {
        @Override
        public void windowClosing(WindowEvent windowEvent)
        {
            int choice = Dialogs.displayExitQuestionDialog(gui);
            if (choice == JOptionPane.YES_OPTION)
            {
                _dataReciever.finish();
                dispose();
            }
        }
    });

The finish method needs to be run to break a while loop to ultimately let the thread finish. Here is the finish method.

public void finish()
{
    _isRunning = false; // This boolean shall break a while loop.
    _listener = null;
    try
    {
        _processInputStream.close();
        System.out.println("Closed input stream");

        _inputStreamReader.close();
        System.out.println("Closed input stream reader");

        _reader.close();
        System.out.println("Closed reader");
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

The problem is that I can't figure out how to close the BufferedReader from "outside" so that the line

while ((line = _reader.readLine()) != null)

is skipped.

Here is the thread that deadlocks (it needs to finish as soon as the user closes the gui).

@Override
public void run()
{
    _isRunning = true;
    CommandManager commandManager = new CommandManager();
    Process process = null;
    try
    {
        process = commandManager.makeCommand(MqttCoammands.MOSQUITTO_SUB,
                "HFC_001", "");
        System.out.println("Mosquitto Sub Command generated.");
        _processInputStream = process.getInputStream();
        _inputStreamReader = new InputStreamReader(_processInputStream);
        _reader = new BufferedReader(_inputStreamReader);

        String line = null;
        while (_isRunning)
        {
            while ((line = _reader.readLine()) != null) // The program deadlocks in this line when the GUI is closed
            {
                String[] splits = line.split(";");
                _parameterList = Arrays.asList(splits);
                System.out.println(_parameterList.toString());
                _listener.get(_parameterList);
            }
        }
        System.out.println("Left the While loop. Preparing end of Thread.");
        _listener = null;
        //            finish();
    }
    catch (IllegalCommandException e1)
    {
        e1.printStackTrace();
    }
    catch (UnsupportedOperatingSystemException e1)
    {
        e1.printStackTrace();
    }
    catch (IOException e1)
    {
        e1.printStackTrace();
    }
}

To close the BufferedReader I tried setting it to null. I tried closing the BufferedReader, InputStreamReader and the InputStream (as you can see in the finish method), but nothing works, the program still deadlocks. Anyone encountered the same problem? Anyone sees the solution?

Thanks in advance!

Edit: I forgot to mention that the last console output before the deadlock is

closed input stream

It comes from the finish method. It implies that the InputStreamReader and the BufferedReader is not beeing closed.

Upvotes: 0

Views: 446

Answers (2)

Dakshinamurthy Karra
Dakshinamurthy Karra

Reputation: 5463

  1. When you create a wrapper around an inputstream/reader - performing close on the wrapper does a close on the wrapped object. So you do not need all those close calls.

  2. I suggest that you stop the process which automatically closes the stream and you receive a null from reader.readLine.

Upvotes: 0

Boris Pavlović
Boris Pavlović

Reputation: 64632

Replace

    while (_isRunning)
    {
        while ((line = _reader.readLine()) != null) // The program deadlocks in this line when the GUI is closed
        {

with

    while (_isRunning && (line = _reader.readLine()) != null)
    {

Upvotes: 0

Related Questions