Search code examples
javaeclipsesocketsdebuggingtelnet

Why this code works only in debug mode with a breakpoint? (IDE Debugger)


Hello I am writing a simple telnet (later im going to have a custom telnet client which interprets the commands) command and control server in pure java and i have a bit of code that works only when I have debugger on and breakpoint in right place this is weird

Code:

Main:

package LiteDoor;

import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

import LiteDoor.net.AcceptTelnetClient;

public class Main {

    public static final String VERSION = "v0.0.1"; 

    public static File scripts = new File("scripts");

    public static ArrayList<AcceptTelnetClient> conns = new ArrayList<AcceptTelnetClient>();

    public static void main(String args[]) throws Exception
    {
        File autorun = new File(scripts.getAbsolutePath()+File.separatorChar+"autorun.litescript");
        if (!autorun.exists()) {
            scripts.mkdirs();
            autorun.createNewFile();
        }

        ServerSocket Soc=new ServerSocket(666);
        while(true)
        {
            Socket CSoc=Soc.accept();
            AcceptTelnetClient ob=new AcceptTelnetClient(CSoc);
        }
    }

}

AcceptTelnetClient:

package LiteDoor.net;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

import LiteDoor.Main;
import LiteDoor.io.MyBufferedWriter;

public class AcceptTelnetClient extends Thread {
    Socket ClientSocket;
    public boolean master;
    public String slaveCmd = null;

    public AcceptTelnetClient(Socket CSoc) throws Exception {
        Main.conns.add(this);

        ClientSocket=CSoc;
        System.out.println("Client Connected ...");
        BufferedReader in  = new BufferedReader(new InputStreamReader(ClientSocket.getInputStream()));
        @SuppressWarnings("resource")
        MyBufferedWriter out = new MyBufferedWriter(new OutputStreamWriter(ClientSocket.getOutputStream()));  

        out.writeln("MASTER/SLAVE?");

        switch(in.readLine().toUpperCase()) {
        case("MASTER"):
            master = true;
            break;
        case("SLAVE"):
            master = false;
            break;
        }

        int i=0;
        while(i<200) {
            out.newLine();
            i++;
        }
        out.flush();

        start();        
    }

    public void run() {
        try {    
            BufferedReader in=new BufferedReader(new InputStreamReader(ClientSocket.getInputStream()));
            @SuppressWarnings("resource")
            MyBufferedWriter out = new MyBufferedWriter(new OutputStreamWriter(ClientSocket.getOutputStream()));  

            out.writeln("");

            if (!master) {
                BufferedReader fr = new BufferedReader(new FileReader(Main.scripts.getAbsolutePath()+File.separatorChar+"autorun.litescript"));
                String line = fr.readLine();
                while(line != null) {
                    if (!line.startsWith("#") && line != "") {
                        out.writeln(line);
                    }
                    line = fr.readLine();
                }
                fr.close();
            }

            boolean loop = true;

            while(loop) {
                if (master) {
                    String cmd = in.readLine();
                    if(cmd.startsWith("quit")) {

                        loop=false;

                    } else {  
                        System.out.println("Master says: " + cmd);
                        for (AcceptTelnetClient con : Main.conns) {
                            if (!con.master) {
                                synchronized (con) {
                                    con.slaveCmd = cmd;
                                }
                            }
                        }
                    }
                } else {
                    if (slaveCmd != null) {
                        synchronized (this) { // Here needs to be an breakpoint
                            out.writeln(slaveCmd);
                            slaveCmd = null;
                        }
                    }
                }
            }
            ClientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ClientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } 
}

What shloud happen:

Client 1 connects to server types in "slave" and waits till some commands get sended to it

Client 2 connects types in "master" and sends some commands that then shloud get sended to all clients that are connected as "slave"

What happens: Client 1 connects as slave Client 2 connects as master sends a command but slaves dont get it (it does not show in telnet client window)

Code works properly only in debugger and with breakpoint in right place

PS yes i tried googling but found nothing


Solution

  • TL;DR...

    you can not be sure that the running thread gets an updated value of the boolean flag master, declare that volatile instead...

     public volatile boolean master;