[Haiku-commits] r31219 - haiku/trunk/src/apps/debugger

bonefish at BerliOS bonefish at mail.berlios.de
Wed Jun 24 02:16:23 CEST 2009


Author: bonefish
Date: 2009-06-24 02:16:22 +0200 (Wed, 24 Jun 2009)
New Revision: 31219
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31219&view=rev

Modified:
   haiku/trunk/src/apps/debugger/Debugger.cpp
   haiku/trunk/src/apps/debugger/MessageCodes.h
   haiku/trunk/src/apps/debugger/TeamDebugger.cpp
   haiku/trunk/src/apps/debugger/TeamDebugger.h
Log:
Fixed the application quit mechanism. Due to the two levels of asynchronous
message sending the main thread exit()ed before the team debugger could process
its quit message. We're no longer taking the detour via Debugger when quitting
a window. The team debugger just quits and synchronously notifies the
application, which in turn waits until all team debugger threads have gone.


Modified: haiku/trunk/src/apps/debugger/Debugger.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/Debugger.cpp	2009-06-23 23:09:36 UTC (rev 31218)
+++ haiku/trunk/src/apps/debugger/Debugger.cpp	2009-06-24 00:16:22 UTC (rev 31219)
@@ -13,6 +13,7 @@
 #include <Application.h>
 #include <Message.h>
 
+#include <AutoLocker.h>
 #include <ObjectList.h>
 
 #include "debug_utils.h"
@@ -163,11 +164,12 @@
 }
 
 
-class Debugger : public BApplication {
+class Debugger : public BApplication, private TeamDebugger::Listener {
 public:
 	Debugger()
 		:
-		BApplication(kDebuggerSignature)
+		BApplication(kDebuggerSignature),
+		fRunningTeamDebuggers(0)
 	{
 	}
 
@@ -178,17 +180,14 @@
 	virtual void MessageReceived(BMessage* message)
 	{
 		switch (message->what) {
-			case MSG_DEBUGGER_QUIT_REQUESTED:
+			case MSG_TEAM_DEBUGGER_QUIT:
 			{
-				TeamDebugger* debugger = NULL;
-				if (message->FindPointer("debugger",
-					(void**)&debugger) == B_OK
-					&& fTeamDebuggers.HasItem(debugger)) {
-					fTeamDebuggers.RemoveItem(debugger);
-					debugger->DeleteSelf();
-					if (fTeamDebuggers.CountItems() == 0)
-						PostMessage(B_QUIT_REQUESTED);
-				}
+				int32 threadID;
+				if (message->FindInt32("thread", &threadID) == B_OK)
+					wait_for_thread(threadID, NULL);
+
+				if (--fRunningTeamDebuggers == 0)
+					Quit();
 				break;
 			}
 			default:
@@ -255,23 +254,45 @@
 			return;
 		}
 
-		debugger = new(std::nothrow) TeamDebugger;
+		debugger = new(std::nothrow) TeamDebugger(this);
 		if (debugger == NULL) {
 			// TODO: Notify the user!
 			fprintf(stderr, "Error: Out of memory!\n");
 		}
 
-		if (debugger->Init(team, thread, stopInMain) == B_OK
-			&& fTeamDebuggers.AddItem(debugger)) {
+		status_t error = debugger->Init(team, thread, stopInMain);
+		if (debugger->Thread())
+			fRunningTeamDebuggers++;
+
+		if (error == B_OK && fTeamDebuggers.AddItem(debugger)) {
 printf("debugger for team %ld created and initialized successfully!\n", team);
 		} else
 			delete debugger;
 	}
 
+private:
+	typedef BObjectList<TeamDebugger>	TeamDebuggerList;
+
+private:
+	// TeamDebugger::Listener
+	virtual void TeamDebuggerQuit(TeamDebugger* debugger)
+	{
+		// Note: Locking here only works, since we're never locking the other
+		// way around. If we even need to do that, we'll have to introduce a
+		// separate lock to protect the list.
+		AutoLocker<Debugger> locker(this);
+		fTeamDebuggers.RemoveItem(debugger);
+		locker.Unlock();
+
+		if (debugger->Thread() >= 0) {
+			BMessage message(MSG_TEAM_DEBUGGER_QUIT);
+			message.AddInt32("thread", debugger->Thread());
+			PostMessage(&message);
+		}
+	}
+
 	virtual bool QuitRequested()
 	{
-		// TODO:...
-//		return true;
 		// NOTE: The default implementation will just ask all windows'
 		// QuitRequested() hooks. This in turn will ask the TeamWindows.
 		// For now, this is what we want. If we have more windows later,
@@ -282,12 +303,17 @@
 		// QuitReqested() hook or the TeamsWindow and other global windows
 		// could always return false in their QuitRequested().
 		return BApplication::QuitRequested();
+			// TODO: This is ugly. The team debuggers own the windows, not the
+			// other way around.
 	}
 
-private:
-	typedef BObjectList<TeamDebugger>	TeamDebuggerList;
+	virtual void Quit()
+	{
+		// don't quit before all team debuggers have been quit
+		if (fRunningTeamDebuggers <= 0)
+			BApplication::Quit();
+	}
 
-private:
 	TeamDebugger* _TeamDebuggerForTeam(team_id teamID) const
 	{
 		for (int32 i = 0; TeamDebugger* debugger = fTeamDebuggers.ItemAt(i);
@@ -301,6 +327,7 @@
 
 private:
 	TeamDebuggerList	fTeamDebuggers;
+	int32				fRunningTeamDebuggers;
 };
 
 

Modified: haiku/trunk/src/apps/debugger/MessageCodes.h
===================================================================
--- haiku/trunk/src/apps/debugger/MessageCodes.h	2009-06-23 23:09:36 UTC (rev 31218)
+++ haiku/trunk/src/apps/debugger/MessageCodes.h	2009-06-24 00:16:22 UTC (rev 31219)
@@ -21,7 +21,7 @@
 	MSG_STACK_FRAME_SOURCE_CODE_CHANGED	= 'sfsc',
 	MSG_USER_BREAKPOINT_CHANGED			= 'ubrc',
 
-	MSG_DEBUGGER_QUIT_REQUESTED			= 'dbqt'
+	MSG_TEAM_DEBUGGER_QUIT				= 'dbqt'
 };
 
 

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-23 23:09:36 UTC (rev 31218)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-24 00:16:22 UTC (rev 31219)
@@ -11,7 +11,6 @@
 #include <new>
 
 #include <Alert.h>
-#include <Application.h>
 #include <Message.h>
 
 #include <AutoLocker.h>
@@ -26,9 +25,10 @@
 #include "TeamDebugModel.h"
 
 
-TeamDebugger::TeamDebugger()
+TeamDebugger::TeamDebugger(Listener* listener)
 	:
 	BLooper("team debugger"),
+	fListener(listener),
 	fTeam(NULL),
 	fDebugModel(NULL),
 	fTeamID(-1),
@@ -63,6 +63,8 @@
 	delete fWorker;
 	delete fDebugModel;
 	delete fTeam;
+
+	fListener->TeamDebuggerQuit(this);
 }
 
 
@@ -189,14 +191,6 @@
 
 
 void
-TeamDebugger::DeleteSelf()
-{
-	Lock();
-	Quit();
-}
-
-
-void
 TeamDebugger::MessageReceived(BMessage* message)
 {
 	switch (message->what) {
@@ -323,14 +317,10 @@
 bool
 TeamDebugger::TeamWindowQuitRequested(TeamWindow* window)
 {
-	// TODO: Is this what shall happen?
-	if (!fTeam->Lock())
-		return true;
-
+	AutoLocker< ::Team> locker(fTeam);
 	BString name(fTeam->Name());
+	locker.Unlock();
 
-	fTeam->Unlock();
-
 	BString message;
 	message << "What shall be done about the debugged team '";
 	message << name;
@@ -354,14 +344,11 @@
 		case 1:
 			return false;
 		case 2:
-			// Detach from the team and resume and stopped threads. Seems to be
-			// the default action anyways.
+			// Detach from the team and resume and stopped threads.
 			break;
 	}
 
-	BMessage quitMessage(MSG_DEBUGGER_QUIT_REQUESTED);
-	quitMessage.AddPointer("debugger", this);
-	be_app->PostMessage(&quitMessage);
+	PostMessage(B_QUIT_REQUESTED);
 
 	return true;
 }
@@ -891,3 +878,11 @@
 	// create it and don't care anymore. Maybe an error window, which can
 	// display a list of errors would be the better choice.
 }
+
+
+// #pragma mark - Listener
+
+
+TeamDebugger::Listener::~Listener()
+{
+}

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.h
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-23 23:09:36 UTC (rev 31218)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-24 00:16:22 UTC (rev 31219)
@@ -20,10 +20,13 @@
 class TeamDebugModel;
 
 
-class TeamDebugger : private BLooper, private TeamWindow::Listener,
+class TeamDebugger : public BLooper, private TeamWindow::Listener,
 	private JobListener, private Team::Listener {
 public:
-								TeamDebugger();
+	class Listener;
+
+public:
+								TeamDebugger(Listener* listener);
 								~TeamDebugger();
 
 			status_t			Init(team_id teamID, thread_id threadID,
@@ -31,11 +34,9 @@
 
 			team_id				TeamID() const	{ return fTeamID; }
 
-			void				DeleteSelf();
+	virtual	void				MessageReceived(BMessage* message);
 
 private:
-	virtual	void				MessageReceived(BMessage* message);
-
 	// TeamWindow::Listener
 	virtual	void				StackFrameSourceCodeRequested(
 									TeamWindow* window, StackFrame* frame);
@@ -111,6 +112,7 @@
 									const char* text,...);
 
 private:
+			Listener*			fListener;
 			::Team*				fTeam;
 			TeamDebugModel*		fDebugModel;
 			team_id				fTeamID;
@@ -123,4 +125,13 @@
 			bool				fKillTeamOnQuit;
 };
 
+
+class TeamDebugger::Listener {
+public:
+	virtual						~Listener();
+
+	virtual	void				TeamDebuggerQuit(TeamDebugger* debugger) = 0;
+};
+
+
 #endif	// TEAM_DEBUGGER_H




More information about the Haiku-commits mailing list