Hello,

I would like to revisit this topic again. I don't know if anyone attempting to implement JDWP is having startup problems, but I certainly am with gij. Basically, we need to know exactly when the entire JDWP backend is ready to go, otherwise we end up trying to send event notifications before the debugger is attached and all kinds of other mess.

So I've come up with a rather hacky approach to do this synchronization. The idea is simple: gnu.classpath.jdwp.Jdwp, which already does initialization in its own thread, now contains basically a condition variable. When the condition variable hits a certain count (indicating that all subcomponents are initialized), the thread sets the global "isDebugging" flag, and exits. Thus the caller can simply join or WaitForSingleObject on that thread. When it exits, everything is ready.

While this *is* hacky (a thread exit doesn't really sound like a very explicit/obvious way of implementing this), but it is extremely simple. I tried using "standard" Object.wait-like stuff for this, but it seems to me that while this would be trivial to implement with gcj, it might be quite sloppy in other VMs which have to use JNI. [Besides I haven't gotten that to work properly with gij -- it seems I can't get something(s) set up sufficiently to allow Object.wait to be called.]

I've attached the patches for this scheme. What do people think? [I'll include a changelog entry for the heck of it, I guess.]

I would appreciate comments (for or against).

Keith

ChangeLog
2006-06-15  Keith Seitz  <[EMAIL PROTECTED]>

        * gnu/classpath/jdwp/Jdwp.java (_initLock): New field.
        (_initCount): New field.
        (Jdwp): Don't set isDebugging until fully initialized.
        (subcomponentInitialized): New method.
        (run): Wait for PacketProcessor and JdwpConnection to
        startup, then set isDebugging, and then let this thread
        die.
        * gnu/classpath/jdwp/transport/JdwpConnection.java
        (run): Add synchronization notification.
        * gnu/classpath/jdwp/processor/PacketProcessor.java
        (run): Likewise.
Index: gnu/classpath/jdwp/Jdwp.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/classpath/jdwp/Jdwp.java,v
retrieving revision 1.6
diff -u -p -r1.6 Jdwp.java
--- gnu/classpath/jdwp/Jdwp.java	16 Mar 2006 23:26:10 -0000	1.6
+++ gnu/classpath/jdwp/Jdwp.java	15 Jun 2006 22:00:34 -0000
@@ -56,6 +56,9 @@ import java.util.HashMap;
 /**
  * Main interface from the virtual machine to the JDWP back-end.
  *
+ * The thread created by this class is only used for initialization.
+ * Once it exits, the JDWP backend is fully initialized.
+ *
  * @author Keith Seitz ([EMAIL PROTECTED])
  */
 public class Jdwp
@@ -65,7 +68,8 @@ public class Jdwp
   private static Jdwp _instance = null;
 
   /**
-   * Are we debugging?
+   * Are we debugging? Only true if debugging
+   * *and* initialized.
    */
   public static boolean isDebugging = false;
 
@@ -89,13 +93,16 @@ public class Jdwp
   // A thread group for the JDWP threads
   private ThreadGroup _group;
 
+  // Initialization synchronization
+  private Object _initLock = new Object ();
+  private int _initCount = 0;
+
   /**
    * constructor
    */
   public Jdwp ()
   {
     _shutdown = false;
-    isDebugging = true;
     _instance = this;
   }
 
@@ -271,17 +278,47 @@ public class Jdwp
       }
   }
 
+  /**
+   * Allows subcomponents to specify that they are
+   * initialized.
+   *
+   * Subcomponents include JdwpConnection and PacketProcessor.
+   */
+  public void subcomponentInitialized ()
+  {
+    synchronized (_initLock)
+      {
+	++_initCount;
+	_initLock.notify ();
+      }
+  }
+
   public void run ()
   {
     try
       {
 	_doInitialization ();
+
+	/* We need a little internal synchronization here, so that
+	   when this thread dies, the back-end will be fully initialized,
+	   ready to start servicing the VM and debugger. */
+	while (_initCount != 2)
+	  {
+	    synchronized (_initLock)
+	      {
+		_initLock.wait ();
+	      }
+	  }
+	_initLock = null;
       }
     catch (Throwable t)
       {
 	System.out.println ("Exception in JDWP back-end: " + t);
 	System.exit (1);
       }
+
+    // Now we are finally ready and initialized
+    isDebugging = true;
   }
 
   // A helper function to process the configure string "-Xrunjdwp:..."
Index: gnu/classpath/jdwp/transport/JdwpConnection.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/classpath/jdwp/transport/JdwpConnection.java,v
retrieving revision 1.5
diff -u -p -r1.5 JdwpConnection.java
--- gnu/classpath/jdwp/transport/JdwpConnection.java	3 Sep 2005 00:22:30 -0000	1.5
+++ gnu/classpath/jdwp/transport/JdwpConnection.java	15 Jun 2006 22:00:34 -0000
@@ -1,5 +1,5 @@
 /* JdwpConnection.java -- A JDWP-speaking connection
-   Copyright (C) 2005 Free Software Foundation
+   Copyright (C) 2005, 2006 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -165,6 +165,10 @@ public class JdwpConnection
    */
   public void run ()
   {
+    // Notify initialization thread (gnu.classpath.jdwp.Jdwp) that
+    // the JdwpConnection thread is ready.
+    Jdwp.getDefault().subcomponentInitialized ();
+
     while (!_shutdown)
       {
 	try
Index: gnu/classpath/jdwp/processor/PacketProcessor.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/classpath/jdwp/processor/PacketProcessor.java,v
retrieving revision 1.5
diff -u -p -r1.5 PacketProcessor.java
--- gnu/classpath/jdwp/processor/PacketProcessor.java	27 Jul 2005 19:04:14 -0000	1.5
+++ gnu/classpath/jdwp/processor/PacketProcessor.java	15 Jun 2006 22:00:34 -0000
@@ -1,6 +1,6 @@
 /* PacketProcessor.java -- a thread which processes command packets
    from the debugger
-   Copyright (C) 2005 Free Software Foundation
+   Copyright (C) 2005, 2006 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -137,6 +137,10 @@ public class PacketProcessor
    */
   public Object run ()
   {
+    // Notify initialization thread (gnu.classpath.jdwp.Jdwp) that
+    // the PacketProcessor thread is ready.
+    Jdwp.getDefault().subcomponentInitialized ();
+	
     try
       {
         while (!_shutdown)
@@ -144,7 +148,7 @@ public class PacketProcessor
             _processOnePacket ();
           }
       }
-    catch (IOException ex)
+    catch (Exception ex)
       {
         ex.printStackTrace();
       }

Reply via email to