@@ -1445,9 +1445,7 @@ class GoDebugSession extends LoggingDebugSession {
14451445
14461446 // If called when setting breakpoint internally, we want the error to bubble up.
14471447 const errorCallback = calledWhenSettingBreakpoint ? null : ( err : any ) => {
1448- if ( err ) {
1449- logError ( 'Failed to continue - ' + err . toString ( ) ) ;
1450- }
1448+ this . logDelveError ( err , 'Failed to continue' ) ;
14511449 this . handleReenterDebug ( 'breakpoint' ) ;
14521450 throw err ;
14531451 } ;
@@ -1466,7 +1464,7 @@ class GoDebugSession extends LoggingDebugSession {
14661464 log ( 'NextRequest' ) ;
14671465 this . delve . call < DebuggerState | CommandOut > ( 'Command' , [ { name : 'next' } ] , ( err , out ) => {
14681466 if ( err ) {
1469- logError ( 'Failed to next - ' + err . toString ( ) ) ;
1467+ this . logDelveError ( err , 'Failed to next' ) ;
14701468 }
14711469 const state = this . delve . isApiV1 ? < DebuggerState > out : ( < CommandOut > out ) . State ;
14721470 log ( 'next state' , state ) ;
@@ -1481,7 +1479,7 @@ class GoDebugSession extends LoggingDebugSession {
14811479 log ( 'StepInRequest' ) ;
14821480 this . delve . call < DebuggerState | CommandOut > ( 'Command' , [ { name : 'step' } ] , ( err , out ) => {
14831481 if ( err ) {
1484- logError ( 'Failed to step - ' + err . toString ( ) ) ;
1482+ this . logDelveError ( err , 'Failed to step - ' ) ;
14851483 }
14861484 const state = this . delve . isApiV1 ? < DebuggerState > out : ( < CommandOut > out ) . State ;
14871485 log ( 'stop state' , state ) ;
@@ -1496,7 +1494,7 @@ class GoDebugSession extends LoggingDebugSession {
14961494 log ( 'StepOutRequest' ) ;
14971495 this . delve . call < DebuggerState | CommandOut > ( 'Command' , [ { name : 'stepOut' } ] , ( err , out ) => {
14981496 if ( err ) {
1499- logError ( 'Failed to stepout - ' + err . toString ( ) ) ;
1497+ this . logDelveError ( err , 'Failed to stepout - ' ) ;
15001498 }
15011499 const state = this . delve . isApiV1 ? < DebuggerState > out : ( < CommandOut > out ) . State ;
15021500 log ( 'stepout state' , state ) ;
@@ -1587,6 +1585,59 @@ class GoDebugSession extends LoggingDebugSession {
15871585 } ) ;
15881586 }
15891587
1588+ private logDelveError ( err : any , message : string ) {
1589+ if ( err ) {
1590+ let errorMessage = err . toString ( ) ;
1591+ // Handle unpropagated fatalpanic errors with a more user friendly message:
1592+ // https://github.com/microsoft/vscode-go/issues/1903#issuecomment-460126884
1593+ // https://github.com/go-delve/delve/issues/852
1594+ // This affects macOS only although we're agnostic of the OS at this stage, only handle the error
1595+ if ( errorMessage === 'bad access' ) {
1596+ errorMessage = 'unpropagated fatalpanic: signal SIGSEGV (EXC_BAD_ACCESS). This fatalpanic is not traceable on macOS, see https://github.com/go-delve/delve/issues/852' ;
1597+ }
1598+ logError ( message + ' - ' + errorMessage ) ;
1599+ }
1600+ this . dumpStacktrace ( ) ;
1601+ }
1602+
1603+ private dumpStacktrace ( ) {
1604+ const goroutineId = 0 ;
1605+ const stackTraceIn = { id : goroutineId , depth : this . delve . stackTraceDepth } ;
1606+ if ( ! this . delve . isApiV1 ) {
1607+ Object . assign ( stackTraceIn , { full : false , cfg : this . delve . loadConfig } ) ;
1608+ }
1609+ this . delve . call < DebugLocation [ ] | StacktraceOut > ( this . delve . isApiV1 ? 'StacktraceGoroutine' : 'Stacktrace' , [ stackTraceIn ] , ( err , out ) => {
1610+ if ( err ) {
1611+ logError ( 'Failed to produce stack trace!' ) ;
1612+ return ;
1613+ }
1614+ const locations = this . delve . isApiV1 ? < DebugLocation [ ] > out : ( < StacktraceOut > out ) . Locations ;
1615+ log ( 'locations' , locations ) ;
1616+ const stackFrames = locations . map ( ( location , frameId ) => {
1617+ const uniqueStackFrameId = this . stackFrameHandles . create ( [ goroutineId , frameId ] ) ;
1618+ return new StackFrame (
1619+ uniqueStackFrameId ,
1620+ location . function ? location . function . name : '<unknown>' ,
1621+ location . file === '<autogenerated>' ? null : new Source (
1622+ basename ( location . file ) ,
1623+ this . toLocalPath ( location . file )
1624+ ) ,
1625+ location . line ,
1626+ 0
1627+ ) ;
1628+ } ) ;
1629+ logError ( 'Immediate stacktrace:' ) ;
1630+ let output = '' ;
1631+ stackFrames . forEach ( stackFrame => {
1632+ output = output . concat ( `\t${ stackFrame . source . path } :${ stackFrame . line } \n` ) ;
1633+ if ( stackFrame . name ) {
1634+ output = output . concat ( `\t\t${ stackFrame . name } \n` ) ;
1635+ }
1636+ } ) ;
1637+ logError ( output ) ;
1638+ } ) ;
1639+ }
1640+
15901641 private addFullyQualifiedName ( variables : DebugVariable [ ] ) {
15911642 variables . forEach ( local => {
15921643 local . fullyQualifiedName = local . name ;
0 commit comments