← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/debugger_stop_command into lp:zorba

 

Gabriel Petrovay has proposed merging lp:~zorba-coders/zorba/debugger_stop_command into lp:zorba.

Requested reviews:
  Gabriel Petrovay (gabipetrovay)
  David Graf (davidagraf)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/debugger_stop_command/+merge/88107

Implemented the stop command.
Fixed termination on Windows.
TODO: still a problem on Windows when quitting the debugger client: a zorba store is shut down and in the store destructor a lock hangs the execution of xqdb forever. Not even Ctrl-C helps (probably because everything is called from the exit function in main.cpp)
-- 
https://code.launchpad.net/~zorba-coders/zorba/debugger_stop_command/+merge/88107
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'bin/debugger/command_line_handler.cpp'
--- bin/debugger/command_line_handler.cpp	2012-01-03 12:10:06 +0000
+++ bin/debugger/command_line_handler.cpp	2012-01-10 20:09:25 +0000
@@ -116,7 +116,7 @@
       }
     }
   }
-  theWaitFor = theClient->stop();
+  theWaitFor = theClient->stop(true);
   theClient->quit();
   theQuit = true;
 }
@@ -131,6 +131,13 @@
 
 template<>
 void
+CommandLineHandler::handle<Stop>(ZORBA_TR1_NS::tuple<> &t)
+{
+  theWaitFor = theClient->stop(false);
+}
+
+template<>
+void
 CommandLineHandler::handle<BreakpointSet>(std::tr1::tuple<bstring, bstring, bint> &aTuple)
 {
   DebuggerClient::BreakpointType lType = DebuggerClient::Line;
@@ -271,6 +278,9 @@
   // DBGP: run
   *theCommandLine << createCommand<Run>(TUPLE(), "run", *this, "Run the query");
 
+  // DBGP: stop
+  *theCommandLine << createCommand<Stop>(TUPLE(), "stop", *this, "Stop the query");
+
   // DBGP: breakpoint_set
   {
     std::set<std::string> lAliases;

=== modified file 'bin/debugger/command_line_handler.h'
--- bin/debugger/command_line_handler.h	2012-01-03 12:10:06 +0000
+++ bin/debugger/command_line_handler.h	2012-01-10 20:09:25 +0000
@@ -35,6 +35,7 @@
     Variables,
     Quit,
     Run,
+    Stop,
     BreakpointSet,
     BreakpointGet,
     BreakpointRemove,
@@ -132,10 +133,13 @@
 
 template<>
 void CommandLineHandler::handle<Run> (ZORBA_TR1_NS::tuple<> &t);
-  
+
+template<>
+void CommandLineHandler::handle<Stop> (ZORBA_TR1_NS::tuple<> &t);
+
 template<>
 void CommandLineHandler::handle<StackDepth> (ZORBA_TR1_NS::tuple<>& t);
-  
+
 template<>
 void CommandLineHandler::handle<BreakpointList> (ZORBA_TR1_NS::tuple<>& aTuple);
   

=== modified file 'bin/debugger/event_handler.cpp'
--- bin/debugger/event_handler.cpp	2011-12-21 14:40:33 +0000
+++ bin/debugger/event_handler.cpp	2012-01-10 20:09:25 +0000
@@ -91,8 +91,7 @@
   } catch (ZorbaException& e) {
     std::cerr << "FATAL: could not execute query: " << std::endl;
     std::cerr << e << std::endl;
-    std::cerr << "This is a bug, please report to zorba-users@xxxxxxxxxxxxxxxxxxxxx" << std::endl;
-    //theContinueProducer.produce(false);
+    std::cerr << "This is a bug, please report it at http://bugs.launchpad.net/zorba"; << std::endl;
   }
 }
   

=== modified file 'bin/debugger/main.cpp'
--- bin/debugger/main.cpp	2012-01-05 13:19:14 +0000
+++ bin/debugger/main.cpp	2012-01-10 20:09:25 +0000
@@ -78,9 +78,6 @@
 };
 
 
-XqdbClient* theClient;
-
-
 void
 onExitProcess(ExitCode aExitCode) {
   //if (aExitCode != -1) {
@@ -89,12 +86,12 @@
   std::cout << "Terminating debugger client."<< std::endl;
   // TODO: and the memory?
 
-  delete theClient;
   exit(aExitCode);
 }
 
+
 int
-startZorba(std::string& aExec, std::vector<std::string>& aArgs) 
+startZorba(std::string& aExec, std::vector<std::string>& aArgs, std::auto_ptr<ProcessListener>& aProcessListener) 
 {
 #ifdef WIN32
   // **************************
@@ -143,7 +140,7 @@
 
   if (lResult) {
     // Watch the process
-    ProcessListener* lPl = new ProcessListener(piProcessInfo.hProcess, &onExitProcess);
+    aProcessListener.reset(new ProcessListener(piProcessInfo.dwProcessId, &onExitProcess));
   }
   else {
     // CreateProcess failed
@@ -215,7 +212,7 @@
     }
     
     // Watch the process
-    new ProcessListener(pID, &onExitProcess);
+    aProcessListener.reset(new ProcessListener(pID, &onExitProcess));
 
     return 0;
   }
@@ -357,8 +354,11 @@
     // **************************************************************************
     // start a zorba
 
+    // This is a process listener used to watch the Zorba process termination.
+    std::auto_ptr<ProcessListener> lProcessListener;
+
     if (!lStandalone) {
-      int lResult = startZorba(lZorbaExec, lZorbaArgs);
+      int lResult = startZorba(lZorbaExec, lZorbaArgs, lProcessListener);
       if (lResult) {
         return lResult;
       }
@@ -369,13 +369,10 @@
     // **************************************************************************
     // start the debugger command line
 
-    theClient =  new XqdbClient(lPort);
+    std::auto_ptr<XqdbClient> theClient(new XqdbClient(lPort));
     theClient->start();
 
-    delete theClient;
-
   } catch (...) {
-    delete theClient;
     return -1;
   }
 

=== modified file 'bin/debugger/process_listener.cpp'
--- bin/debugger/process_listener.cpp	2012-01-05 13:19:14 +0000
+++ bin/debugger/process_listener.cpp	2012-01-10 20:09:25 +0000
@@ -62,16 +62,20 @@
   ProcessId lPid = lThis->getProcessID();
 
 #ifdef WIN32
-  // wait for the process to exit
-  WaitForSingleObject(lPid, INFINITE);
-
-  // find out the process exit code if possible
-  if (!GetExitCodeProcess(lThis->getProcessID(), &lExitCode)) {
-    lExitCode = -1;
+  HANDLE lProcessHandle = OpenProcess(SYNCHRONIZE, false, lPid);
+  if (lProcessHandle != NULL) {
+    // wait for the process to exit
+    DWORD lResult = WaitForSingleObject(lProcessHandle, INFINITE);
+ 
+    // find out the process exit code if possible
+    if (!GetExitCodeProcess(lProcessHandle, &lExitCode)) {
+      lExitCode = -1;
+    }
+    DWORD dw = GetLastError();
+ 
+    // wait a little for zorba to dump the garbage
+    Sleep(1000);
   }
-
-  // wait a little for zorba to dump the garbage
-  Sleep(1000);
 #else
   int lChildExitStatus;
 

=== modified file 'bin/debugger/process_listener.h'
--- bin/debugger/process_listener.h	2012-01-05 13:19:14 +0000
+++ bin/debugger/process_listener.h	2012-01-10 20:09:25 +0000
@@ -29,7 +29,7 @@
 #else
 # include <windows.h>
   typedef DWORD ThreadId;
-  typedef HANDLE ProcessId;
+  typedef DWORD ProcessId;
   typedef DWORD ExitCode;
 # define ZORBA_THREAD_RETURN DWORD WINAPI
 #endif

=== modified file 'include/zorba/debugger_client.h'
--- include/zorba/debugger_client.h	2011-12-21 14:40:33 +0000
+++ include/zorba/debugger_client.h	2012-01-10 20:09:25 +0000
@@ -273,9 +273,13 @@
      * This command tells the debug engine, that it should
      * break the execution at the next point possible.
      *
+     * @param withQuit This is a Zorba extension of the DBGP protocol that
+     *    controls if the client should terminate execution and quit (true)
+     *    or only terminate execution but not quit (false). This is used
+     *    by command line clients that implement multiple query runs.
      * @return The id of this request
      */
-    virtual std::size_t stop() = 0;
+    virtual std::size_t stop(bool withQuit) = 0;
     
     /**
      * @brief Send the detach command to the debug engine.

=== modified file 'src/debugger/debugger_clientimpl.cpp'
--- src/debugger/debugger_clientimpl.cpp	2011-12-21 14:40:33 +0000
+++ src/debugger/debugger_clientimpl.cpp	2012-01-10 20:09:25 +0000
@@ -213,10 +213,14 @@
 }
   
 std::size_t
-DebuggerClientImpl::stop()
+DebuggerClientImpl::stop(bool withQuit)
 {
   std::size_t id = ++theLastId;
-  *theOutStream << "stop -i " << id << '\0';
+  *theOutStream << "stop -i " << id;
+  if (!withQuit) {
+    *theOutStream << " -z 1";
+  }
+  *theOutStream << '\0';
   theOutStream->flush();
   return id;
 }

=== modified file 'src/debugger/debugger_clientimpl.h'
--- src/debugger/debugger_clientimpl.h	2011-12-21 14:40:33 +0000
+++ src/debugger/debugger_clientimpl.h	2012-01-10 20:09:25 +0000
@@ -57,7 +57,7 @@
     virtual std::size_t step_into();
     virtual std::size_t step_out();
     virtual std::size_t step_over();
-    virtual std::size_t stop();
+    virtual std::size_t stop(bool withQuit = true);
     virtual std::size_t detach();
     virtual std::size_t breakpoint_set(BreakpointType aType,
                                        bool aEnabled = true,

=== modified file 'src/debugger/debugger_communicator.cpp'
--- src/debugger/debugger_communicator.cpp	2011-12-21 14:40:33 +0000
+++ src/debugger/debugger_communicator.cpp	2012-01-10 20:09:25 +0000
@@ -74,13 +74,17 @@
   }
 }
 
+#ifdef NDEBUG
+# define TIMEOUT 6
+#else
+# define TIMEOUT 60
+#endif
+
 void
 DebuggerCommunicator::connect()
 {
-	for (int i = 0; i < 5 && !theSocket; i++)
-  {
-		try
-    {
+	for (int i = 0; i < TIMEOUT && !theSocket; i++) {
+		try {
 			// Connect to the client on the given host and port
       std::auto_ptr<TCPSocket> lSocket(new TCPSocket(theHost, thePort));
       theSocket = lSocket.release();
@@ -91,10 +95,9 @@
       theResponseQueue = new ResponseQueue(theCommunicatorOutStream);
       theResponseQueue->start();
 		}
-    catch (DebuggerSocketException& /* e */)
-    {
+    catch (DebuggerSocketException& /* e */) {
       // Wait one second before trying to reconnect
-      msleep(100);
+      msleep(1000);
 		}
   }
 }

=== modified file 'src/debugger/debugger_runtime.cpp'
--- src/debugger/debugger_runtime.cpp	2012-01-03 12:10:06 +0000
+++ src/debugger/debugger_runtime.cpp	2012-01-10 20:09:25 +0000
@@ -67,7 +67,6 @@
     theCommunicator(communicator),
     theWrapper(theQuery->generateWrapper()),
     theExecStatus(QUERY_IDLE),
-    theNotSendTerminateEvent(false),
     thePlanIsOpen(false),
     theSerializer(0),
     theItemHandler(aHandler),
@@ -89,6 +88,14 @@
   theWrapper->open();
   thePlanIsOpen = true;
   runQuery();
+
+  std::stringstream lResult;
+  lResult << "<response command=\"" << theLastContinuationCommand.second << "\" "
+    << "status=\"stopping\" "
+    << "reason=\"ok\" "
+    << "transaction_id=\"" << theLastContinuationCommand.first << "\">"
+    << "</response>";
+  theCommunicator->send(lResult.str());
 }
 
 void
@@ -107,7 +114,6 @@
   theWrapper = theQuery->generateWrapper();
   thePlanIsOpen = false;
   theExecStatus = QUERY_IDLE;
-  theNotSendTerminateEvent = false;
   reset();
 }
 
@@ -324,15 +330,6 @@
 {
   AutoLock lLock(theLock, Lock::WRITE);
   theExecStatus = QUERY_TERMINATED;
-
-  std::stringstream lResult;
-  lResult << "<response command=\"" << theLastContinuationCommand.second << "\" "
-    << "status=\"stopping\" "
-    << "reason=\"ok\" "
-    << "transaction_id=\"" << theLastContinuationCommand.first << "\">"
-    << "</response>";
-  theCommunicator->send(lResult.str());
-  // TODO: something more here?
 }
 
 
@@ -503,13 +500,6 @@
 }
 
 
-void
-DebuggerRuntime::setNotSendTerminateEvent()
-{
-  theNotSendTerminateEvent = true;
-}
-
-
 std::list<std::pair<zstring, zstring> >
 DebuggerRuntime::eval(zstring& aExpr)
 {

=== modified file 'src/debugger/debugger_runtime.h'
--- src/debugger/debugger_runtime.h	2012-01-03 12:10:06 +0000
+++ src/debugger/debugger_runtime.h	2012-01-10 20:09:25 +0000
@@ -67,9 +67,6 @@
   public:
 
     void
-    setNotSendTerminateEvent();
-
-    void
     resetRuntime();
 
     ExecutionStatus
@@ -173,7 +170,6 @@
     ExecutionStatus                   theExecStatus;
     mutable Lock                      theLock;
     std::set<DebugIterator*>          theBreakpoints;
-    bool                              theNotSendTerminateEvent;
     bool                              thePlanIsOpen;
     serializer*                       theSerializer;
     itemHandler                       theItemHandler;

=== modified file 'src/debugger/debugger_server.cpp'
--- src/debugger/debugger_server.cpp	2012-01-03 12:10:06 +0000
+++ src/debugger/debugger_server.cpp	2012-01-10 20:09:25 +0000
@@ -78,6 +78,8 @@
   init();
 
   std::string lCommand;
+  std::string lCommandName;
+  int lTransactionID = 0;
 
   while (!theStopping &&
       theRuntime->getExecutionStatus() != QUERY_DETACHED) {
@@ -86,6 +88,9 @@
     theCommunicator->receive(lCommand);
     DebuggerCommand lCmd = DebuggerCommand(lCommand);
 
+    lCommandName = lCmd.getName();
+    lCmd.getArg("i", lTransactionID);
+
     if (theRuntime->getExecutionStatus() == QUERY_TERMINATED) {
       // clone the existing runtime
       DebuggerRuntime* lNewRuntime = theRuntime->clone();
@@ -108,7 +113,16 @@
   }
 
   theRuntime->terminate();
-  theRuntime->resetRuntime();
+
+  std::stringstream lResult;
+  lResult << "<response command=\"" << lCommandName << "\" "
+    << "status=\"stopped\" "
+    << "reason=\"ok\" "
+    << "transaction_id=\"" << lTransactionID << "\">"
+    << "</response>";
+  theCommunicator->send(lResult.str());
+
+  //theRuntime->resetRuntime();
   theRuntime->join();
 
   return true;
@@ -473,10 +487,18 @@
 
       } else if (aCommand.getName() == "stop") {
         theRuntime->setLastContinuationCommand(lTransactionID, aCommand.getName());
-        theStopping = true;
+        // sending the zorba extensions flag, the debugger server will not terminate
+        // when the stop command is sent. This way the zorba debugger client can
+        // perform multiple execution of the same query even when the user terminates
+        // the execution using the stop command.
+        // NOTE: theStopping is controlling the main debugger server loop
+        if (!lZorbaExtensions) {
+          theStopping = true;
+        }
 
-        lResponse << "reason=\"ok\" status=\"stopped\" ";
+        lResponse << "status=\"stopping\" reason=\"ok\"";
         lResponse << ">";
+
         theRuntime->terminateRuntime();
 
       } else if (aCommand.getName() == "stack_depth") {
@@ -531,8 +553,7 @@
         theRuntime->stepOver();
         return "";
       } else if (aCommand.getName() == "step_out") {
-        ExecutionStatus lStatus = theRuntime->getExecutionStatus();
-        if (lStatus != QUERY_SUSPENDED) {
+        if (theRuntime->getExecutionStatus() != QUERY_SUSPENDED) {
           return buildErrorResponse(lTransactionID, lCmdName, 6, "Can not step out since the execution is not started.");
         }
         theRuntime->setLastContinuationCommand(lTransactionID, aCommand.getName());


Follow ups