* 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:
@@ -5,6 +5,7 @@
|
||||
#ifndef _DEBUGGER_H
|
||||
#define _DEBUGGER_H
|
||||
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <image.h>
|
||||
@@ -17,6 +18,7 @@
|
||||
#include <arch/mipsel/arch_debugger.h>
|
||||
#include <arch/arm/arch_debugger.h>
|
||||
|
||||
|
||||
#ifdef __INTEL__
|
||||
typedef struct x86_debug_cpu_state debug_cpu_state;
|
||||
#elif __POWERPC__
|
||||
@@ -64,6 +66,7 @@ enum {
|
||||
B_TEAM_DEBUG_TEAM_CREATION = 0x00080000,
|
||||
B_TEAM_DEBUG_THREADS = 0x00100000,
|
||||
B_TEAM_DEBUG_IMAGES = 0x00200000,
|
||||
B_TEAM_DEBUG_PREVENT_EXIT = 0x00400000,
|
||||
|
||||
// new thread handling
|
||||
B_TEAM_DEBUG_STOP_NEW_THREADS = 0x01000000,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <errno.h>
|
||||
@@ -25,6 +26,7 @@
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
#define USE_GUI true
|
||||
// define to false if the debug server shouldn't use GUI (i.e. an alert)
|
||||
|
||||
@@ -35,9 +37,11 @@
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
using std::map;
|
||||
using std::nothrow;
|
||||
|
||||
|
||||
static const char *kSignature = "application/x-vnd.Haiku-debug_server";
|
||||
|
||||
// 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";
|
||||
|
||||
|
||||
// KillTeam
|
||||
static void
|
||||
KillTeam(team_id team, const char *appName = NULL)
|
||||
{
|
||||
@@ -71,7 +74,7 @@ KillTeam(team_id team, const char *appName = NULL)
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// DebugMessage
|
||||
|
||||
class DebugMessage : public DoublyLinkedListLinkImpl<DebugMessage> {
|
||||
public:
|
||||
DebugMessage()
|
||||
@@ -92,7 +95,6 @@ private:
|
||||
typedef DoublyLinkedList<DebugMessage> DebugMessageList;
|
||||
|
||||
|
||||
// TeamDebugHandler
|
||||
class TeamDebugHandler : public BLocker {
|
||||
public:
|
||||
TeamDebugHandler(team_id team);
|
||||
@@ -144,11 +146,11 @@ private:
|
||||
};
|
||||
|
||||
|
||||
// TeamDebugHandlerRoster
|
||||
class TeamDebugHandlerRoster : public BLocker {
|
||||
private:
|
||||
TeamDebugHandlerRoster()
|
||||
: BLocker("team debug handler roster")
|
||||
:
|
||||
BLocker("team debug handler roster")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -259,7 +261,6 @@ private:
|
||||
TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL;
|
||||
|
||||
|
||||
// DebugServer
|
||||
class DebugServer : public BServer {
|
||||
public:
|
||||
DebugServer(status_t &error);
|
||||
@@ -285,13 +286,14 @@ private:
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// constructor
|
||||
|
||||
TeamDebugHandler::TeamDebugHandler(team_id team)
|
||||
: BLocker("team debug handler"),
|
||||
fMessages(),
|
||||
fMessageCountSem(-1),
|
||||
fTeam(team),
|
||||
fHandlerThread(-1)
|
||||
:
|
||||
BLocker("team debug handler"),
|
||||
fMessages(),
|
||||
fMessageCountSem(-1),
|
||||
fTeam(team),
|
||||
fHandlerThread(-1)
|
||||
{
|
||||
fDebugContext.nub_port = -1;
|
||||
fDebugContext.reply_port = -1;
|
||||
@@ -299,7 +301,7 @@ TeamDebugHandler::TeamDebugHandler(team_id team)
|
||||
fExecutablePath[0] = '\0';
|
||||
}
|
||||
|
||||
// destructor
|
||||
|
||||
TeamDebugHandler::~TeamDebugHandler()
|
||||
{
|
||||
// delete the message count semaphore and wait for the thread to die
|
||||
@@ -322,7 +324,7 @@ TeamDebugHandler::~TeamDebugHandler()
|
||||
}
|
||||
}
|
||||
|
||||
// Init
|
||||
|
||||
status_t
|
||||
TeamDebugHandler::Init(port_id nubPort)
|
||||
{
|
||||
@@ -352,6 +354,13 @@ TeamDebugHandler::Init(port_id nubPort)
|
||||
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
|
||||
char name[B_OS_NAME_LENGTH];
|
||||
snprintf(name, sizeof(name), "team %ld message count", fTeam);
|
||||
@@ -377,14 +386,14 @@ TeamDebugHandler::Init(port_id nubPort)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// Team
|
||||
|
||||
team_id
|
||||
TeamDebugHandler::Team() const
|
||||
{
|
||||
return fTeam;
|
||||
}
|
||||
|
||||
// PushMessage
|
||||
|
||||
status_t
|
||||
TeamDebugHandler::PushMessage(DebugMessage *message)
|
||||
{
|
||||
@@ -396,7 +405,7 @@ TeamDebugHandler::PushMessage(DebugMessage *message)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _PopMessage
|
||||
|
||||
status_t
|
||||
TeamDebugHandler::_PopMessage(DebugMessage *&message)
|
||||
{
|
||||
@@ -418,7 +427,7 @@ TeamDebugHandler::_PopMessage(DebugMessage *&message)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _EnterDebugger
|
||||
|
||||
thread_id
|
||||
TeamDebugHandler::_EnterDebugger()
|
||||
{
|
||||
@@ -482,14 +491,14 @@ TeamDebugHandler::_EnterDebugger()
|
||||
return thread;
|
||||
}
|
||||
|
||||
// _KillTeam
|
||||
|
||||
void
|
||||
TeamDebugHandler::_KillTeam()
|
||||
{
|
||||
KillTeam(fTeam, fTeamInfo.args);
|
||||
}
|
||||
|
||||
// _HandleMessage
|
||||
|
||||
bool
|
||||
TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
||||
{
|
||||
@@ -577,7 +586,7 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
||||
return kill;
|
||||
}
|
||||
|
||||
// _LookupSymbolAddress
|
||||
|
||||
void
|
||||
TeamDebugHandler::_LookupSymbolAddress(
|
||||
debug_symbol_lookup_context *lookupContext, const void *address,
|
||||
@@ -631,7 +640,7 @@ TeamDebugHandler::_LookupSymbolAddress(
|
||||
}
|
||||
}
|
||||
|
||||
// _PrintStackTrace
|
||||
|
||||
void
|
||||
TeamDebugHandler::_PrintStackTrace(thread_id thread)
|
||||
{
|
||||
@@ -707,7 +716,6 @@ TeamDebugHandler::_NotifyRegistrar(team_id team, bool openAlert,
|
||||
}
|
||||
|
||||
|
||||
// _InitGUI
|
||||
status_t
|
||||
TeamDebugHandler::_InitGUI()
|
||||
{
|
||||
@@ -716,14 +724,14 @@ TeamDebugHandler::_InitGUI()
|
||||
return app->InitGUIContext();
|
||||
}
|
||||
|
||||
// _HandlerThreadEntry
|
||||
|
||||
status_t
|
||||
TeamDebugHandler::_HandlerThreadEntry(void *data)
|
||||
{
|
||||
return ((TeamDebugHandler*)data)->_HandlerThread();
|
||||
}
|
||||
|
||||
// _HandlerThread
|
||||
|
||||
status_t
|
||||
TeamDebugHandler::_HandlerThread()
|
||||
{
|
||||
@@ -806,35 +814,35 @@ TeamDebugHandler::_HandlerThread()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _ExecutableNameEquals
|
||||
|
||||
bool
|
||||
TeamDebugHandler::_ExecutableNameEquals(const char *name) const
|
||||
{
|
||||
return strcmp(_LastPathComponent(fExecutablePath), name) == 0;
|
||||
}
|
||||
|
||||
// _IsAppServer
|
||||
|
||||
bool
|
||||
TeamDebugHandler::_IsAppServer() const
|
||||
{
|
||||
return _ExecutableNameEquals("app_server");
|
||||
}
|
||||
|
||||
// _IsInputServer
|
||||
|
||||
bool
|
||||
TeamDebugHandler::_IsInputServer() const
|
||||
{
|
||||
return _ExecutableNameEquals("input_server");
|
||||
}
|
||||
|
||||
// _IsRegistrar
|
||||
|
||||
bool
|
||||
TeamDebugHandler::_IsRegistrar() const
|
||||
{
|
||||
return _ExecutableNameEquals("registrar");
|
||||
}
|
||||
|
||||
// _IsGUIServer
|
||||
|
||||
bool
|
||||
TeamDebugHandler::_IsGUIServer() const
|
||||
{
|
||||
@@ -842,7 +850,7 @@ TeamDebugHandler::_IsGUIServer() const
|
||||
return _IsAppServer() || _IsInputServer() || _IsRegistrar();
|
||||
}
|
||||
|
||||
// _LastPathComponent
|
||||
|
||||
const char *
|
||||
TeamDebugHandler::_LastPathComponent(const char *path)
|
||||
{
|
||||
@@ -850,7 +858,7 @@ TeamDebugHandler::_LastPathComponent(const char *path)
|
||||
return lastSlash ? lastSlash + 1 : path;
|
||||
}
|
||||
|
||||
// _FindTeam
|
||||
|
||||
team_id
|
||||
TeamDebugHandler::_FindTeam(const char *name)
|
||||
{
|
||||
@@ -868,7 +876,7 @@ TeamDebugHandler::_FindTeam(const char *name)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
// _AreGUIServersAlive
|
||||
|
||||
bool
|
||||
TeamDebugHandler::_AreGUIServersAlive()
|
||||
{
|
||||
@@ -879,16 +887,17 @@ TeamDebugHandler::_AreGUIServersAlive()
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// constructor
|
||||
|
||||
DebugServer::DebugServer(status_t &error)
|
||||
: BServer(kSignature, false, &error),
|
||||
fListenerPort(-1),
|
||||
fListener(-1),
|
||||
fTerminating(false)
|
||||
:
|
||||
BServer(kSignature, false, &error),
|
||||
fListenerPort(-1),
|
||||
fListener(-1),
|
||||
fTerminating(false)
|
||||
{
|
||||
}
|
||||
|
||||
// Init
|
||||
|
||||
status_t
|
||||
DebugServer::Init()
|
||||
{
|
||||
@@ -904,6 +913,7 @@ DebugServer::Init()
|
||||
return fListener;
|
||||
|
||||
// register as default debugger
|
||||
// TODO: could set default flags
|
||||
status_t error = install_default_debugger(fListenerPort);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
@@ -922,14 +932,14 @@ DebugServer::QuitRequested()
|
||||
return false;
|
||||
}
|
||||
|
||||
// _ListenerEntry
|
||||
|
||||
status_t
|
||||
DebugServer::_ListenerEntry(void *data)
|
||||
{
|
||||
return ((DebugServer*)data)->_Listener();
|
||||
}
|
||||
|
||||
// _Listener
|
||||
|
||||
status_t
|
||||
DebugServer::_Listener()
|
||||
{
|
||||
@@ -963,7 +973,7 @@ message->Data().origin.team, code));
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// main
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
||||
@@ -3496,7 +3496,8 @@ void
|
||||
_user_exit_team(status_t returnValue)
|
||||
{
|
||||
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.reason = THREAD_RETURN_EXIT;
|
||||
@@ -3507,6 +3508,13 @@ _user_exit_team(status_t returnValue)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user