rem: printf("debug_server: Thread %ld entered the debugger: %s\n", fThread, buffer);   #if 1  void *ip = NULL; void *stackFrameAddress = NULL; debug_context context; status_t error = init_debug_context(&context, message->Data().origin.nub_port);  if (error == B_OK) { error = debug_get_instruction_pointer(&context, message->Data().origin.thread, &ip, &stackFrameAddress); }  if (error == B_OK) { printf("stack trace, current PC %p:\n", ip);  for (int32 i = 0; i < 50; i++) { debug_stack_frame_info stackFrameInfo;  error = debug_get_stack_frame(&context, stackFrameAddress, &stackFrameInfo); if (error < B_OK || stackFrameInfo.parent_frame == NULL) break;  printf("  (%p)  %p\n", stackFrameInfo.frame, stackFrameInfo.return_address); stackFrameAddress = stackFrameInfo.parent_frame; } } #endif  BMessage alertMessage(*fInvoker->Message()); alertMessage.AddInt32("which", 1); fInvoker->Invoke(&alertMessage);  return false;
add: return fThreadDebugHandlers.empty();
context: ThreadDebugHandler::HandleMessage(DebugMessage *message){	if (!fInvoker)		fInvoker = new BInvoker(new BMessage(ALERT_MESSAGE), this);	// get some user-readable message	char buffer[512];	switch (message->Code()) {		case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:			get_debug_exception_string(				message->Data().exception_occurred.exception, buffer,				sizeof(buffer));			break;		case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:		{			// get the debugger() message			void *messageAddress = message->Data().debugger_call.message;			char messageBuffer[128];			debug_context context;			status_t error = init_debug_context(&context,				message->Data().origin.nub_port);			if (error == B_OK) {				ssize_t bytesRead = debug_read_string(&context, messageAddress,					messageBuffer, sizeof(messageBuffer));				if (bytesRead < 0)					error = bytesRead;				destroy_debug_context(&context);			}			if (error == B_OK) {				sprintf(buffer, "Debugger call: `%s'", messageBuffer);			} else {				snprintf(buffer, sizeof(buffer), "Debugger call: %p "					"(Failed to read message: %s)", messageAddress,					strerror(error));			}			break;		}		case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:		case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:		case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:		case B_DEBUGGER_MESSAGE_SINGLE_STEP:		default:			get_debug_message_string(message->Code(), buffer, sizeof(buffer));			break;	}	// TODO: This would be the point to pop up an asynchronous alert.	// We just print the error and send a message to ourselves.	printf("debug_server: Thread %ld entered the debugger: %s\n", fThread,		buffer);// TODO: Temporary solution. Remove when attaching gdb is working.#if 1	// print a stacktrace	void *ip = NULL;	void *stackFrameAddress = NULL;	debug_context context;	status_t error = init_debug_context(&context,		message->Data().origin.nub_port);		if (error == B_OK) {		error = debug_get_instruction_pointer(&context,			message->Data().origin.thread, &ip, &stackFrameAddress);	}	if (error == B_OK) {		printf("stack trace, current PC %p:\n", ip);		for (int32 i = 0; i < 50; i++) {			debug_stack_frame_info stackFrameInfo;			error = debug_get_stack_frame(&context, stackFrameAddress,				&stackFrameInfo);			if (error < B_OK || stackFrameInfo.parent_frame == NULL)				break;			printf("  (%p)  %p\n", stackFrameInfo.frame,				stackFrameInfo.return_address);			stackFrameAddress = stackFrameInfo.parent_frame;		}	}#endif	BMessage alertMessage(*fInvoker->Message());	alertMessage.AddInt32("which", 1);	fInvoker->Invoke(&alertMessage);	return false;}