Thread scheduling problem in Linux jdk-1.1.7B ============================================= I am currently developing a GUI for an upcoming game server "VC" (telnet external.nj.nec.com 4000). After finishing the graphics part I thought the rest - that is connecting the GUI to the server via socket - would be trivial. Well - it's not. It seems that the thread scheduler doesn't continue threads which wait for I/O although all other threads are waiting. The appended code illustrates the problem. "TestSocket" connects an applet to the text-based server (VC), awaits keyboard input which it sends to VC, and writes VC messages to stout. Depending on the global flags RUN_TICKER and COMMUNICATE TestSocket's behaviour can be changed to illustrate the problems. On my machine (kernel 2.2.5, RedHat 6.0, jdk-1.1.7B-glibc, green_threads) the program - started by "java TestSocket" - behaves like follows: RUN_TICKER = false, COMMUNICATE = false : no connection to VC, keyboard input echoed to stdout. OK RUN_TICKER = false, COMMUNICATE = true : connection to VC established - OK, but keyboard input is no longer being echoed. br.readLine() seems to hang. Messages from VC are correctly written to stdout, though. unusable RUN_TICKER = true, COMMUNICATE = true : connection to VC established - OK. "ticker" is a max-priority thread which stays in a loop sleeping and printing dots. Now, keyboard inputs are echoed but not sent to the server. This indicates that a socket related thread is hanging. The funny thing, however, is that when a message is sent to the applet from the server it is correctly displayed as before and seems to unlock the write routine. After reading a message from VC the keyboard command gets delivered to VC. better, but still unusable In this application all threads are sleeping most of the time. Unless I am a victim of some nasty selfmade deadlock I think the reported behaviour is due to a scheduler bug. NB.: The original applet is working under Netscape-4.6 Java. Comments - and especially workarounds - are very welcome. -- Michael Buro [EMAIL PROTECTED] NEC Research Institute 4 Independence Way, Tel: +1 (609) 951-2703 Princeton NJ 08540 USA Fax: +1 (609) 951-2488 http://www.neci.nj.nec.com/homepages/mic Appendix: ========= Here is how to log on VC to repeat the experiments: > telnet external.nj.nec.com 4000 <return> > ... asking for login & password (arbitrary) > tell mic hi <return> sends "hi" to the applet > who <return> reports connected users. Typed into the stdin window, the list of connected users should be sent to the applet and written on stdout. The code: // TestSocket.java import java.io.*; import java.net.*; import java.applet.*; import java.awt.*; import java.awt.event.*; import SocketComm; import Ticker; // not yet a real applet. start via "main" public class TestSocket extends Applet { public static final boolean RUN_TICKER = false; public static final boolean COMMUNICATE = true; SocketComm sc = null; VCReader vcr = null; Thread ticker = null; class VCReader extends Thread { public VCReader() { // connect to VC String s = ""; try { s = sc.connect("external.nj.nec.com", 4000, "mic", ""); } catch(UnknownHostException f) { throw new Error("" + f); } catch(IOException f) { throw new Error("" + f); } // print all received messages System.out.println(s); } public void run() { // handle messages coming from VC while (true) { String s = sc.read_line(); System.out.println(s); } } } TestSocket() { sc = new SocketComm(); ticker = new Thread(new Ticker(1000)); ticker.setPriority(Thread.MAX_PRIORITY); if (RUN_TICKER) ticker.start(); if (COMMUNICATE) { vcr = new VCReader(); vcr.start(); } } public static void main(String[] args) throws IOException { TestSocket ts = new TestSocket(); BufferedReader br = new BufferedReader (new InputStreamReader(System.in)); System.out.println("so far so good"); while (true) { String line = br.readLine(); System.out.println("input was: " + line); if (TestSocket.COMMUNICATE) ts.sc.write_line(line); } } } /////////////////////////////////////////////////////////////// // SocketCom.java import java.io.*; import java.net.*; import java.util.*; class SocketComm { private String host; private int port; private Socket so; private BufferedReader br; private BufferedWriter bw; public SocketComm() { host = null; port = 0; so = null; br = null; bw = null; } public void write_line(String line) { try { bw.write(line); bw.newLine(); bw.flush(); } catch(IOException e) { System.out.println("write_line: " + e); System.exit(-1); } } public String read_line() { String s = ""; try { s = br.readLine(); } catch (IOException e) { System.out.println("read_line: " + e); System.exit(-1); } return s; } // return all messages sent from server public String connect(String host, int port, String name, String password) throws IOException, UnknownHostException { System.out.println("trying to connect " + name + "@" + host + ":" + port); String collected = ""; this.host = host; this.port = port; so = new Socket(host, port); if (false) { // test exception IOException e = new IOException("connect: test"); throw e; } br = new BufferedReader(new InputStreamReader(so.getInputStream())); bw = new BufferedWriter(new OutputStreamWriter(so.getOutputStream())); String line; // wait for login prompt while (true) { line = br.readLine(); collected += line + "\n"; if (line.endsWith("use).")) break; } // send login write_line(name); // wait for password prompt while (true) { line = br.readLine(); collected += line + "\n"; if (line.endsWith("password: ")) break; } // send password write_line(password); // wait for READY while (true) { line = br.readLine(); collected += line + "\n"; if (line.endsWith("READY")) break; } System.out.println("connected"); // done return collected; } } ///////////////////////////////////////////////////////////////////////// // Misc.java public class Misc { public static void sleep(int n) { try { Thread.currentThread().sleep(n); } catch(InterruptedException e) {;} } } //////////////////////////////////////////////////////////////////////// // Ticker.java import java.lang.*; public class Ticker implements Runnable { int interval; public Ticker(int interval) { this.interval = interval; } public void run() { while (true) { Misc.sleep(interval); System.out.println("."); } } } ---------------------------------------------------------------------- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]