* Correctly set debug_origin::nub_port in all concerned functions.

* Now a debugged thread and the debug nub thread are not longer blocking
  on ports when they receive a SIGKILL[THR] (we couldn't kill a debugged
  team before).
* Small fixes. More correct cleanup when the debug nub thread terminates.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11491 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2005-02-25 14:30:16 +00:00
parent 3b28d367cb
commit 6d3794c0a1

View File

@ -10,6 +10,7 @@
#include <debugger.h>
#include <kernel.h>
#include <KernelExport.h>
#include <ksignal.h>
#include <ksyscalls.h>
#include <sem.h>
#include <team.h>
@ -33,6 +34,24 @@ static port_id sDefaultDebuggerPort = -1;
static status_t ensure_debugger_installed(team_id teamID, port_id *port = NULL);
static ssize_t
kill_interruptable_read_port(port_id port, int32 *code, void *buffer,
size_t bufferSize)
{
return read_port_etc(port, code, buffer, bufferSize,
B_KILL_CAN_INTERRUPT, 0);
}
static status_t
kill_interruptable_write_port(port_id port, int32 code, const void *buffer,
size_t bufferSize)
{
return write_port_etc(port, code, buffer, bufferSize,
B_KILL_CAN_INTERRUPT, 0);
}
/**
* The team lock must be held.
*/
@ -133,8 +152,8 @@ prepare_thread_stopped_message(debug_thread_stopped &message,
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = nubPort;
message.why = whyStopped;
message.nub_port = nubPort;
message.data = data;
arch_get_debug_cpu_state(&message.cpu_state);
}
@ -239,8 +258,8 @@ thread_hit_debug_event(uint32 event, const void *message, int32 size,
// read a command from the debug port
int32 command;
debugged_thread_message_data commandMessage;
ssize_t commandMessageSize = read_port(port, &command,
&commandMessage, sizeof(commandMessage));
ssize_t commandMessageSize = kill_interruptable_read_port(port,
&command, &commandMessage, sizeof(commandMessage));
if (commandMessageSize < 0) {
error = commandMessageSize;
TRACE(("thread_hit_debug_event(): thread: %ld, failed to "
@ -275,10 +294,8 @@ thread_hit_debug_event(uint32 event, const void *message, int32 size,
teamDebugInfo.nub_port, additionalData);
// send it
do {
error = write_port(debuggerPort, event, &stoppedMessage,
sizeof(stoppedMessage));
} while (error == B_INTERRUPTED);
error = kill_interruptable_write_port(debuggerPort, event,
&stoppedMessage, sizeof(stoppedMessage));
break;
}
@ -322,6 +339,7 @@ user_debug_pre_syscall(uint32 syscall, void *args)
debug_pre_syscall message;
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = thread->team->debug_info.nub_port;
message.syscall = syscall;
// copy the syscall args
@ -356,6 +374,7 @@ user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue,
debug_post_syscall message;
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = thread->team->debug_info.nub_port;
message.start_time = startTime;
message.end_time = system_time();
message.return_value = returnValue;
@ -387,7 +406,7 @@ stop_thread(debug_why_stopped whyStopped, void *additionalData)
// prepare the message
debug_thread_stopped message;
prepare_thread_stopped_message(message, B_THREAD_NOT_RUNNING, nubPort,
prepare_thread_stopped_message(message, whyStopped, nubPort,
additionalData);
return thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_STOPPED, &message,
@ -426,6 +445,7 @@ user_debug_handle_signal(int signal, struct sigaction *handler, bool deadly)
debug_signal_received message;
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = thread->team->debug_info.nub_port;
message.signal = signal;
message.handler = *handler;
message.deadly = deadly;
@ -459,6 +479,7 @@ user_debug_team_created(team_id teamID)
debug_team_created message;
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = thread->team->debug_info.nub_port;
message.new_team = teamID;
thread_hit_debug_event(B_DEBUGGER_MESSAGE_TEAM_CREATED, &message,
@ -473,6 +494,7 @@ user_debug_team_deleted(team_id teamID, port_id debuggerPort)
debug_team_deleted message;
message.origin.thread = -1;
message.origin.team = teamID;
message.origin.nub_port = -1;
write_port_etc(debuggerPort, B_DEBUGGER_MESSAGE_TEAM_DELETED, &message,
sizeof(message), B_RELATIVE_TIMEOUT, 0);
// TODO: Would it be OK to wait here?
@ -495,6 +517,7 @@ user_debug_thread_created(thread_id threadID)
debug_thread_created message;
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = thread->team->debug_info.nub_port;
message.new_thread = threadID;
thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_CREATED, &message,
@ -532,6 +555,7 @@ user_debug_thread_deleted(team_id teamID, thread_id threadID)
debug_thread_deleted message;
message.origin.thread = threadID;
message.origin.team = teamID;
message.origin.nub_port = -1;
write_port_etc(debuggerPort, B_DEBUGGER_MESSAGE_THREAD_DELETED,
&message, sizeof(message), B_RELATIVE_TIMEOUT, 0);
// TODO: Would it be OK to wait here?
@ -554,6 +578,7 @@ user_debug_image_created(const image_info *imageInfo)
debug_image_created message;
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = thread->team->debug_info.nub_port;
memcpy(&message.info, imageInfo, sizeof(image_info));
thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
@ -576,6 +601,7 @@ user_debug_image_deleted(const image_info *imageInfo)
debug_image_deleted message;
message.origin.thread = thread->id;
message.origin.team = thread->team->id;
message.origin.nub_port = thread->team->debug_info.nub_port;
memcpy(&message.info, imageInfo, sizeof(image_info));
thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
@ -583,6 +609,31 @@ user_debug_image_deleted(const image_info *imageInfo)
}
static void
nub_thread_cleanup(struct thread *nubThread)
{
team_debug_info teamDebugInfo;
bool destroyDebugInfo = false;
cpu_status state = disable_interrupts();
GRAB_TEAM_LOCK();
team_debug_info &info = nubThread->team->debug_info;
if (info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED
&& info.nub_thread == nubThread->id) {
teamDebugInfo = info;
clear_team_debug_info(&info);
destroyDebugInfo = true;
}
RELEASE_TEAM_LOCK();
restore_interrupts(state);
if (destroyDebugInfo)
destroy_team_debug_info(&teamDebugInfo);
}
static status_t
debug_nub_thread(void *)
{
@ -606,22 +657,14 @@ debug_nub_thread(void *)
while (true) {
int32 command;
debug_nub_message_data message;
ssize_t messageSize = read_port(port, &command, &message,
sizeof(message));
if (messageSize < 0) {
// The port is not longer valid: If we are still listed in the
// team's debug info as nub thread, we need to update that.
cpu_status state = disable_interrupts();
GRAB_TEAM_LOCK();
ssize_t messageSize = kill_interruptable_read_port(port, &command,
&message, sizeof(message));
team_debug_info &info = nubThread->team->debug_info;
if (info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED
&& info.nub_thread == nubThread->id) {
clear_team_debug_info(&info);
}
RELEASE_TEAM_LOCK();
restore_interrupts(state);
if (messageSize < 0) {
// The port is not longer valid or we were interrupted by a kill
// signal: If we are still listed in the team's debug info as nub
// thread, we need to update that.
nub_thread_cleanup(nubThread);
TRACE(("nub thread %ld: terminating: %lx\n", nubThread->id,
messageSize));
@ -824,8 +867,17 @@ debug_nub_thread(void *)
}
// send the reply, if necessary
if (sendReply)
write_port(replyPort, command, &reply, replySize);
if (sendReply) {
status_t error = kill_interruptable_write_port(replyPort, command,
&reply, replySize);
if (error != B_OK) {
// The debugger port is either not longer existing or we got
// interrupted by a kill signal. In either case we terminate.
nub_thread_cleanup(nubThread);
return error;
}
}
}
}
@ -854,6 +906,9 @@ TRACE(("install_team_debugger(team: %ld, port: %ld, default: %d, "
: team_get_team_struct_locked(teamID));
if (team) {
// get a real team ID
teamID = team->id;
if (team == team_get_kernel_team()) {
// don't allow to debug the kernel
error = B_NOT_ALLOWED;