From 769d46fe2baa105ad2f0ee0241fd932991fa2646 Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 29 Jan 2019 01:09:28 +0000 Subject: [PATCH 1/2] debug: use unique stack frame id --- src/debugAdapter/goDebug.ts | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts index f38daefbd..3c7df5165 100644 --- a/src/debugAdapter/goDebug.ts +++ b/src/debugAdapter/goDebug.ts @@ -551,6 +551,7 @@ class GoDebugSession extends LoggingDebugSession { private delve: Delve; private localPathSeparator: string; private remotePathSeparator: string; + private stackFrameHandles: Handles<[number, number]>; private packageInfo = new Map(); private launchArgs: LaunchRequestArguments; private logLevel: Logger.LogLevel = Logger.LogLevel.Error; @@ -565,6 +566,7 @@ class GoDebugSession extends LoggingDebugSession { this.debugState = null; this.delve = null; this.breakpoints = new Map(); + this.stackFrameHandles = new Handles<[number, number]>(); } protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void { @@ -840,7 +842,8 @@ class GoDebugSession extends LoggingDebugSession { protected stackTraceRequest(response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): void { log('StackTraceRequest'); // delve does not support frame paging, so we ask for a large depth - let stackTraceIn = { id: args.threadId, depth: this.delve.stackTraceDepth }; + const goroutineId = args.threadId; + let stackTraceIn = { id: goroutineId, depth: this.delve.stackTraceDepth }; if (!this.delve.isApiV1) { Object.assign(stackTraceIn, { full: false, cfg: this.delve.loadConfig }); } @@ -851,9 +854,10 @@ class GoDebugSession extends LoggingDebugSession { } const locations = this.delve.isApiV1 ? out : (out).Locations; log('locations', locations); - let stackFrames = locations.map((location, i) => - new StackFrame( - i, + let stackFrames = locations.map((location, frameId) => { + const uniqueStackFrameId = this.stackFrameHandles.create([goroutineId, frameId]); + return new StackFrame( + uniqueStackFrameId, location.function ? location.function.name : '', location.file === '' ? null : new Source( basename(location.file), @@ -861,8 +865,8 @@ class GoDebugSession extends LoggingDebugSession { ), location.line, 0 - ) - ); + ); + }); if (args.startFrame > 0) { stackFrames = stackFrames.slice(args.startFrame); } @@ -877,7 +881,8 @@ class GoDebugSession extends LoggingDebugSession { protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void { log('ScopesRequest'); - const listLocalVarsIn = { goroutineID: this.debugState.currentGoroutine.id, frame: args.frameId }; + const [goroutineId, frameId] = this.stackFrameHandles.get(args.frameId); + const listLocalVarsIn = { goroutineID: goroutineId, frame: frameId }; this.delve.call('ListLocalVars', this.delve.isApiV1 ? [listLocalVarsIn] : [{ scope: listLocalVarsIn, cfg: this.delve.loadConfig }], (err, out) => { if (err) { logError('Failed to list local variables - ' + err.toString()); @@ -886,7 +891,7 @@ class GoDebugSession extends LoggingDebugSession { const locals = this.delve.isApiV1 ? out : (out).Variables; log('locals', locals); this.addFullyQualifiedName(locals); - let listLocalFunctionArgsIn = { goroutineID: this.debugState.currentGoroutine.id, frame: args.frameId }; + let listLocalFunctionArgsIn = { goroutineID: goroutineId, frame: frameId }; this.delve.call('ListFunctionArgs', this.delve.isApiV1 ? [listLocalFunctionArgsIn] : [{ scope: listLocalFunctionArgsIn, cfg: this.delve.loadConfig }], (err, outArgs) => { if (err) { logError('Failed to list function args - ' + err.toString()); @@ -1305,9 +1310,10 @@ class GoDebugSession extends LoggingDebugSession { } private evaluateRequestImpl(args: DebugProtocol.EvaluateArguments): Thenable { + const [goroutineId, frameId] = this.stackFrameHandles.get(args.frameId); const scope = { - goroutineID: this.debugState.currentGoroutine.id, - frame: args.frameId + goroutineID: goroutineId, + frame: frameId }; let evalSymbolArgs = this.delve.isApiV1 ? { symbol: args.expression, From 0be26045373f7995aa1b2f08b837f492bdeaa979 Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 29 Jan 2019 01:10:09 +0000 Subject: [PATCH 2/2] debug: clean up handles when reentering the debugger, avoid memory leak Co-authored-by: Joel Hendrix --- src/debugAdapter/goDebug.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts index 3c7df5165..5dec6f838 100644 --- a/src/debugAdapter/goDebug.ts +++ b/src/debugAdapter/goDebug.ts @@ -1171,7 +1171,14 @@ class GoDebugSession extends LoggingDebugSession { return typeName.substr(i + 1); } + private cleanupHandles(): void { + this._variableHandles.reset(); + this.stackFrameHandles.reset(); + } + private handleReenterDebug(reason: string): void { + this.cleanupHandles(); + if (this.debugState.exited) { this.sendEvent(new TerminatedEvent()); log('TerminatedEvent');