This is DebuggerController.m in view mode; [Download] [Up]
#import "DebuggerController_Private.h" #import <Foundation/Foundation.h> /* for the kill() call in -interrupt */ #import <sys/types.h> #import <sys/signal.h> #import "debug.h" static DebuggerController *debuggerController; void fork_and_start_debugger_controller(GdbManager *gm) { (void)[NSRunLoop class]; // workaround: force RunLoop to go thru +initialize // and setup support for multithreading debuggerController = [[DebuggerController alloc] init]; [NSThread detachNewThreadSelector: @selector(startController:) toTarget: debuggerController withObject: gm]; } @implementation DebuggerController - init { [super init]; displayProvider = nil; stdinPFD = nil; return self; } #if 1 - (id) displayProvider { return displayProvider; } #endif // // This is the first method called in the new thread. // Advertise ourself using the given name for the connection. // A Gui system, like ProjectBuilder, will be looking for // us at that name. // // Also, create a connection for our local (i.e. same process) // connection to the GuiGdbManager. // // Then go into the runloop and wait for the Gui system to // give us the DisplayProvider object. // - (void) startController: gm { NSString *localName; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSDistantObject *dP; gdbManager = (GdbManager <GuiGdbManagerInternal, GuiGdbManagerExecLock> *)gm; NSLog(@"Debugger Controller: looking for connection named %@ on host %@", [gdbManager displayProviderConnectionName], [gdbManager displayProviderHostName]); dP = [NSConnection rootProxyForConnectionWithRegisteredName:[gdbManager displayProviderConnectionName] host:[gdbManager displayProviderHostName]]; if ([dP conformsToProtocol:@protocol(GuiDisplayProvider2)]) [dP setProtocolForProxy:@protocol(GuiDisplayProvider2)]; else [dP setProtocolForProxy:@protocol(GuiDisplayProvider)]; displayProviderConnection = [dP connectionForProxy]; displayProvider = (id<GuiDisplayProvider>)[dP retain]; [displayProvider setDebuggerController:self]; localName = [[NSProcessInfo processInfo] globallyUniqueString]; [gdbManager setDebuggerControllerConnectionName:localName]; gdbConnection = [[NSConnection alloc] init]; [gdbConnection setRootObject: self]; [gdbConnection registerName: localName]; DEBUG_PRINT("Dbg Controller: start: exported connections\n"); [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleConnectionDeath:) name: NSConnectionDidDieNotification object: displayProviderConnection]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleConnectionDeath:) name: NSConnectionDidDieNotification object: gdbConnection]; // This has the side-effect of unblocking the gdbManager. [gdbManager setDisplayProvider: dP]; [pool release]; [[NSRunLoop currentRunLoop] run]; } // // Sent by the gdb thread; tells us to look for // activity on stdin. // - (oneway void) gdbReadyForInput { if (stdinPFD == nil) { stdinPFD = [[NSPosixFileDescriptor alloc] initWithFileDescriptor:fileno(stdin)]; [stdinPFD monitorFileActivity: NSPosixReadableActivity delegate: self]; } else [stdinPFD monitorFileActivity: NSPosixReadableActivity]; } // Called from (remote) client of us, e.g. ProjectBuilder // execute cmd in gdb - (oneway void) executeCmd:(NSString *)c withTty:(BOOL)t withAnnotation:(BOOL)a { GdbCmd *cmd; // send cmd to Gdb /* copy of command c should not be needed; work around for DO problems */ cmd = [[GdbCmd alloc] initWithCmd:[c copy] ofType:GDB_CMD_EXEC useTty:t useAnnotation:a]; [gdbManager enqueueCmd:cmd]; } - (oneway void)executeCmd:(NSString*)c withTty:(BOOL)tty withAnnotation:(BOOL)annotation catchOutput:(BOOL)catch { GdbCmd *cmd; // send cmd to Gdb /* copy of command c should not be needed; work around for DO problems */ cmd = [[GdbCmd alloc] initWithCmd:[c copy] ofType:GDB_CMD_EXEC useTty:tty useAnnotation:annotation catchOutput:catch]; [gdbManager enqueueCmd:cmd]; } /* Interrupt; right now, this only interrupts the inferior. Might want to extend this to interrupt gdb thread someday. */ - (oneway void) interrupt { extern int inferior_pid; if (inferior_pid > 0) kill(inferior_pid, SIGINT); } - (void) handleConnectionDeath: (NSNotification *) notification { if ([notification object] == displayProviderConnection) { // client has gone away } else { // gdb connection } // FIXME: do a better job of cleanning up exit(22); } @end // Called when input is pending on stdin @implementation DebuggerController (NSPosixFileDescriptorDelegateMethods) - (void) posixFileDescriptor:(NSPosixFileDescriptor *)pfd currentActivity:(NSPosixFileActivity) activity { GdbCmd *cmd; // turn off monitoring until GDB tells to turn it back on [pfd monitorFileActivity: NSPosixNoActivity]; // send cmd to Gdb (which will wake it up); gdb will read stdin cmd = [[GdbCmd alloc] initWithCmd:nil ofType:GDB_CMD_INPUT_PENDING]; [gdbManager enqueueCmd:cmd]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.