Merge pull request #3549 from junichi11/netbeans-6177-xdebug

[NETBEANS-6177] Fix an issue the stop command is not sent
diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/DebugSession.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/DebugSession.java
index bbc3db5..f39b279 100644
--- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/DebugSession.java
+++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/DebugSession.java
@@ -78,6 +78,7 @@
     private AtomicReference<DebuggerEngine> engine;
     private IDESessionBridge myBridge;
     private AtomicReference<String> myFileName;
+    private volatile boolean canceled;
 
     DebugSession(DebuggerOptions options, BackendLauncher backendLauncher) {
         commands = new LinkedList<>();
@@ -124,6 +125,14 @@
                 } catch (Throwable e) {
                     log(e, Level.SEVERE);
                 }
+                if (canceled) {
+                    synchronized (commands) {
+                        if (commands.isEmpty()) {
+                            detachRequest.set(true);
+                            stop();
+                        }
+                    }
+                }
             }
         } finally {
             postprocess();
@@ -133,7 +142,9 @@
     private void preprocess() {
         detachRequest.set(false);
         stopRequest.set(false);
-        commands.clear();
+        synchronized (commands) {
+            commands.clear();
+        }
         sessionId.set(null);
         myBridge = new IDESessionBridge();
         myFileName = new AtomicReference<>();
@@ -325,14 +336,14 @@
 
     @Override
     public boolean cancel() {
-        // NETBEANS-5080 detach the request
+        // NETBEANS-5080 request cancellation
         // startProcessing() may be called via other ways
         // e.g. via command line: nc -vz localhost 9003(debugger port)
         // First of all, get the socket after the above command is run
         // See: Socket sessionSocket = myServer.accept(); in ServerThread.run()
         // Then, invokeLater.get() is called in startProcessing()
         // Finally, infinite loop occurs in run() becuase do not still receive anything
-        detachRequest.set(true);
+        canceled = true;
         return true;
     }
 
diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/SessionManager.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/SessionManager.java
index 9fc0f60..d6c086b 100644
--- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/SessionManager.java
+++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/SessionManager.java
@@ -101,11 +101,6 @@
 
     public synchronized void stopSession(Session session) {
         SessionId id = session.lookupFirst(null, SessionId.class);
-        // NETBEANS-5080 detach the request of the debug session to finish the task
-        DebugSession debugSession = session.lookupFirst(null, DebugSession.class);
-        if (debugSession != null) {
-            debugSession.cancel();
-        }
         DebugSession debSess = getSession(id);
         if (debSess != null) {
             debSess.stopSession();
@@ -122,6 +117,11 @@
         }
         SessionManager.closeServerThread(session);
         resetBreakpoints();
+        // NETBEANS-5080 request cancellation to finish the task
+        DebugSession debugSession = session.lookupFirst(null, DebugSession.class);
+        if (debugSession != null) {
+            debugSession.cancel();
+        }
     }
 
     public static SessionId getSessionId(Project project) {