* Added new team flag B_TEAM_DEBUG_PREVENT_EXIT that prevents teams from exiting

via exit() (the calling thread will drop into the debugger instead).
* The DebugServer now uses this flag by default.
* Added TODO comment: the default debugger should already be able to set a flag
  like this in order to close a race condition between dropping a thread into
  the debugger and setting the flag.
* Cleaned up the debug_server sources a bit.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36265 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-04-14 18:03:48 +00:00
parent 14e1d73761
commit a608485f26
3 changed files with 64 additions and 43 deletions
+3
View File
@@ -5,6 +5,7 @@
#ifndef _DEBUGGER_H #ifndef _DEBUGGER_H
#define _DEBUGGER_H #define _DEBUGGER_H
#include <signal.h> #include <signal.h>
#include <image.h> #include <image.h>
@@ -17,6 +18,7 @@
#include <arch/mipsel/arch_debugger.h> #include <arch/mipsel/arch_debugger.h>
#include <arch/arm/arch_debugger.h> #include <arch/arm/arch_debugger.h>
#ifdef __INTEL__ #ifdef __INTEL__
typedef struct x86_debug_cpu_state debug_cpu_state; typedef struct x86_debug_cpu_state debug_cpu_state;
#elif __POWERPC__ #elif __POWERPC__
@@ -64,6 +66,7 @@ enum {
B_TEAM_DEBUG_TEAM_CREATION = 0x00080000, B_TEAM_DEBUG_TEAM_CREATION = 0x00080000,
B_TEAM_DEBUG_THREADS = 0x00100000, B_TEAM_DEBUG_THREADS = 0x00100000,
B_TEAM_DEBUG_IMAGES = 0x00200000, B_TEAM_DEBUG_IMAGES = 0x00200000,
B_TEAM_DEBUG_PREVENT_EXIT = 0x00400000,
// new thread handling // new thread handling
B_TEAM_DEBUG_STOP_NEW_THREADS = 0x01000000, B_TEAM_DEBUG_STOP_NEW_THREADS = 0x01000000,
+52 -42
View File
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <map> #include <map>
#include <errno.h> #include <errno.h>
@@ -25,6 +26,7 @@
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#define USE_GUI true #define USE_GUI true
// define to false if the debug server shouldn't use GUI (i.e. an alert) // define to false if the debug server shouldn't use GUI (i.e. an alert)
@@ -35,9 +37,11 @@
# define TRACE(x) ; # define TRACE(x) ;
#endif #endif
using std::map; using std::map;
using std::nothrow; using std::nothrow;
static const char *kSignature = "application/x-vnd.Haiku-debug_server"; static const char *kSignature = "application/x-vnd.Haiku-debug_server";
// paths to the apps used for debugging // paths to the apps used for debugging
@@ -46,7 +50,6 @@ static const char *kTerminalPath = "/boot/system/apps/Terminal";
static const char *kGDBPath = "/bin/gdb"; static const char *kGDBPath = "/bin/gdb";
// KillTeam
static void static void
KillTeam(team_id team, const char *appName = NULL) KillTeam(team_id team, const char *appName = NULL)
{ {
@@ -71,7 +74,7 @@ KillTeam(team_id team, const char *appName = NULL)
// #pragma mark - // #pragma mark -
// DebugMessage
class DebugMessage : public DoublyLinkedListLinkImpl<DebugMessage> { class DebugMessage : public DoublyLinkedListLinkImpl<DebugMessage> {
public: public:
DebugMessage() DebugMessage()
@@ -92,7 +95,6 @@ private:
typedef DoublyLinkedList<DebugMessage> DebugMessageList; typedef DoublyLinkedList<DebugMessage> DebugMessageList;
// TeamDebugHandler
class TeamDebugHandler : public BLocker { class TeamDebugHandler : public BLocker {
public: public:
TeamDebugHandler(team_id team); TeamDebugHandler(team_id team);
@@ -144,11 +146,11 @@ private:
}; };
// TeamDebugHandlerRoster
class TeamDebugHandlerRoster : public BLocker { class TeamDebugHandlerRoster : public BLocker {
private: private:
TeamDebugHandlerRoster() TeamDebugHandlerRoster()
: BLocker("team debug handler roster") :
BLocker("team debug handler roster")
{ {
} }
@@ -259,7 +261,6 @@ private:
TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL; TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL;
// DebugServer
class DebugServer : public BServer { class DebugServer : public BServer {
public: public:
DebugServer(status_t &error); DebugServer(status_t &error);
@@ -285,13 +286,14 @@ private:
// #pragma mark - // #pragma mark -
// constructor
TeamDebugHandler::TeamDebugHandler(team_id team) TeamDebugHandler::TeamDebugHandler(team_id team)
: BLocker("team debug handler"), :
fMessages(), BLocker("team debug handler"),
fMessageCountSem(-1), fMessages(),
fTeam(team), fMessageCountSem(-1),
fHandlerThread(-1) fTeam(team),
fHandlerThread(-1)
{ {
fDebugContext.nub_port = -1; fDebugContext.nub_port = -1;
fDebugContext.reply_port = -1; fDebugContext.reply_port = -1;
@@ -299,7 +301,7 @@ TeamDebugHandler::TeamDebugHandler(team_id team)
fExecutablePath[0] = '\0'; fExecutablePath[0] = '\0';
} }
// destructor
TeamDebugHandler::~TeamDebugHandler() TeamDebugHandler::~TeamDebugHandler()
{ {
// delete the message count semaphore and wait for the thread to die // delete the message count semaphore and wait for the thread to die
@@ -322,7 +324,7 @@ TeamDebugHandler::~TeamDebugHandler()
} }
} }
// Init
status_t status_t
TeamDebugHandler::Init(port_id nubPort) TeamDebugHandler::Init(port_id nubPort)
{ {
@@ -352,6 +354,13 @@ TeamDebugHandler::Init(port_id nubPort)
return error; return error;
} }
// set team flags
debug_nub_set_team_flags message;
message.flags = B_TEAM_DEBUG_PREVENT_EXIT;
send_debug_message(&fDebugContext, B_DEBUG_MESSAGE_SET_TEAM_FLAGS, &message,
sizeof(message), NULL, 0);
// create the message count semaphore // create the message count semaphore
char name[B_OS_NAME_LENGTH]; char name[B_OS_NAME_LENGTH];
snprintf(name, sizeof(name), "team %ld message count", fTeam); snprintf(name, sizeof(name), "team %ld message count", fTeam);
@@ -377,14 +386,14 @@ TeamDebugHandler::Init(port_id nubPort)
return B_OK; return B_OK;
} }
// Team
team_id team_id
TeamDebugHandler::Team() const TeamDebugHandler::Team() const
{ {
return fTeam; return fTeam;
} }
// PushMessage
status_t status_t
TeamDebugHandler::PushMessage(DebugMessage *message) TeamDebugHandler::PushMessage(DebugMessage *message)
{ {
@@ -396,7 +405,7 @@ TeamDebugHandler::PushMessage(DebugMessage *message)
return B_OK; return B_OK;
} }
// _PopMessage
status_t status_t
TeamDebugHandler::_PopMessage(DebugMessage *&message) TeamDebugHandler::_PopMessage(DebugMessage *&message)
{ {
@@ -418,7 +427,7 @@ TeamDebugHandler::_PopMessage(DebugMessage *&message)
return B_OK; return B_OK;
} }
// _EnterDebugger
thread_id thread_id
TeamDebugHandler::_EnterDebugger() TeamDebugHandler::_EnterDebugger()
{ {
@@ -482,14 +491,14 @@ TeamDebugHandler::_EnterDebugger()
return thread; return thread;
} }
// _KillTeam
void void
TeamDebugHandler::_KillTeam() TeamDebugHandler::_KillTeam()
{ {
KillTeam(fTeam, fTeamInfo.args); KillTeam(fTeam, fTeamInfo.args);
} }
// _HandleMessage
bool bool
TeamDebugHandler::_HandleMessage(DebugMessage *message) TeamDebugHandler::_HandleMessage(DebugMessage *message)
{ {
@@ -577,7 +586,7 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
return kill; return kill;
} }
// _LookupSymbolAddress
void void
TeamDebugHandler::_LookupSymbolAddress( TeamDebugHandler::_LookupSymbolAddress(
debug_symbol_lookup_context *lookupContext, const void *address, debug_symbol_lookup_context *lookupContext, const void *address,
@@ -631,7 +640,7 @@ TeamDebugHandler::_LookupSymbolAddress(
} }
} }
// _PrintStackTrace
void void
TeamDebugHandler::_PrintStackTrace(thread_id thread) TeamDebugHandler::_PrintStackTrace(thread_id thread)
{ {
@@ -707,7 +716,6 @@ TeamDebugHandler::_NotifyRegistrar(team_id team, bool openAlert,
} }
// _InitGUI
status_t status_t
TeamDebugHandler::_InitGUI() TeamDebugHandler::_InitGUI()
{ {
@@ -716,14 +724,14 @@ TeamDebugHandler::_InitGUI()
return app->InitGUIContext(); return app->InitGUIContext();
} }
// _HandlerThreadEntry
status_t status_t
TeamDebugHandler::_HandlerThreadEntry(void *data) TeamDebugHandler::_HandlerThreadEntry(void *data)
{ {
return ((TeamDebugHandler*)data)->_HandlerThread(); return ((TeamDebugHandler*)data)->_HandlerThread();
} }
// _HandlerThread
status_t status_t
TeamDebugHandler::_HandlerThread() TeamDebugHandler::_HandlerThread()
{ {
@@ -806,35 +814,35 @@ TeamDebugHandler::_HandlerThread()
return B_OK; return B_OK;
} }
// _ExecutableNameEquals
bool bool
TeamDebugHandler::_ExecutableNameEquals(const char *name) const TeamDebugHandler::_ExecutableNameEquals(const char *name) const
{ {
return strcmp(_LastPathComponent(fExecutablePath), name) == 0; return strcmp(_LastPathComponent(fExecutablePath), name) == 0;
} }
// _IsAppServer
bool bool
TeamDebugHandler::_IsAppServer() const TeamDebugHandler::_IsAppServer() const
{ {
return _ExecutableNameEquals("app_server"); return _ExecutableNameEquals("app_server");
} }
// _IsInputServer
bool bool
TeamDebugHandler::_IsInputServer() const TeamDebugHandler::_IsInputServer() const
{ {
return _ExecutableNameEquals("input_server"); return _ExecutableNameEquals("input_server");
} }
// _IsRegistrar
bool bool
TeamDebugHandler::_IsRegistrar() const TeamDebugHandler::_IsRegistrar() const
{ {
return _ExecutableNameEquals("registrar"); return _ExecutableNameEquals("registrar");
} }
// _IsGUIServer
bool bool
TeamDebugHandler::_IsGUIServer() const TeamDebugHandler::_IsGUIServer() const
{ {
@@ -842,7 +850,7 @@ TeamDebugHandler::_IsGUIServer() const
return _IsAppServer() || _IsInputServer() || _IsRegistrar(); return _IsAppServer() || _IsInputServer() || _IsRegistrar();
} }
// _LastPathComponent
const char * const char *
TeamDebugHandler::_LastPathComponent(const char *path) TeamDebugHandler::_LastPathComponent(const char *path)
{ {
@@ -850,7 +858,7 @@ TeamDebugHandler::_LastPathComponent(const char *path)
return lastSlash ? lastSlash + 1 : path; return lastSlash ? lastSlash + 1 : path;
} }
// _FindTeam
team_id team_id
TeamDebugHandler::_FindTeam(const char *name) TeamDebugHandler::_FindTeam(const char *name)
{ {
@@ -868,7 +876,7 @@ TeamDebugHandler::_FindTeam(const char *name)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
// _AreGUIServersAlive
bool bool
TeamDebugHandler::_AreGUIServersAlive() TeamDebugHandler::_AreGUIServersAlive()
{ {
@@ -879,16 +887,17 @@ TeamDebugHandler::_AreGUIServersAlive()
// #pragma mark - // #pragma mark -
// constructor
DebugServer::DebugServer(status_t &error) DebugServer::DebugServer(status_t &error)
: BServer(kSignature, false, &error), :
fListenerPort(-1), BServer(kSignature, false, &error),
fListener(-1), fListenerPort(-1),
fTerminating(false) fListener(-1),
fTerminating(false)
{ {
} }
// Init
status_t status_t
DebugServer::Init() DebugServer::Init()
{ {
@@ -904,6 +913,7 @@ DebugServer::Init()
return fListener; return fListener;
// register as default debugger // register as default debugger
// TODO: could set default flags
status_t error = install_default_debugger(fListenerPort); status_t error = install_default_debugger(fListenerPort);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -922,14 +932,14 @@ DebugServer::QuitRequested()
return false; return false;
} }
// _ListenerEntry
status_t status_t
DebugServer::_ListenerEntry(void *data) DebugServer::_ListenerEntry(void *data)
{ {
return ((DebugServer*)data)->_Listener(); return ((DebugServer*)data)->_Listener();
} }
// _Listener
status_t status_t
DebugServer::_Listener() DebugServer::_Listener()
{ {
@@ -963,7 +973,7 @@ message->Data().origin.team, code));
// #pragma mark - // #pragma mark -
// main
int int
main() main()
{ {
+9 -1
View File
@@ -3496,7 +3496,8 @@ void
_user_exit_team(status_t returnValue) _user_exit_team(status_t returnValue)
{ {
struct thread* thread = thread_get_current_thread(); struct thread* thread = thread_get_current_thread();
struct thread* mainThread = thread->team->main_thread; struct team* team = thread->team;
struct thread* mainThread = team->main_thread;
mainThread->exit.status = returnValue; mainThread->exit.status = returnValue;
mainThread->exit.reason = THREAD_RETURN_EXIT; mainThread->exit.reason = THREAD_RETURN_EXIT;
@@ -3507,6 +3508,13 @@ _user_exit_team(status_t returnValue)
thread->exit.reason = THREAD_RETURN_EXIT; thread->exit.reason = THREAD_RETURN_EXIT;
} }
if ((atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_PREVENT_EXIT)
!= 0) {
// This team is currently being debugged, and requested that teams
// should not be exited.
user_debug_stop_thread();
}
send_signal(thread->id, SIGKILL); send_signal(thread->id, SIGKILL);
} }