Skip to content

Commit

Permalink
fix: Improve init failure handling (#684)
Browse files Browse the repository at this point in the history
* fix: Auto configure runtimeExecutable when only runtimeArgs are used (built-in web server).

* fix: Improve handling of broken clients.

* Changelog.
  • Loading branch information
zobo authored Oct 30, 2021
1 parent 282a317 commit 85a28a4
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 62 deletions.
19 changes: 15 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,28 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

## [1.21.1]

### Fixed

- Auto configure runtimeExecutable when only runtimeArgs are used (built-in web server).
- Improve handling of broken clients on failed initPacket.

## [1.21.0]

### Added

- Support for maxConnections limiting how many parallel connections the debug adapter allows.

## [1.20.0]

### Added

- Support no-folder debugging in (purple) VS Code.

## [1.19.0]

## Added
### Added

- Support for PHP 8.1 facets
- Support for Xdebug 3.1 xdebug_notify()
Expand All @@ -25,19 +36,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

## [1.17.0]

## Added
### Added

- Added logpoint support.

## [1.16.3]

## Fixed
### Fixed

- Fixed semver dependency error.

## [1.16.2]

## Fixed
### Fixed

- Fixed breakpoint and launch initialization order.
- Optimize feature negotiation for known Xdebug version.
Expand Down
132 changes: 74 additions & 58 deletions src/phpDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,73 +345,89 @@ class PhpDebugSession extends vscode.DebugSession {
this.sendEvent(new vscode.OutputEvent(log), true)
}
})
const initPacket = await connection.waitForInitPacket()
try {
const initPacket = await connection.waitForInitPacket()

// support for breakpoints
let feat: xdebug.FeatureGetResponse
const supportedEngine =
initPacket.engineName === 'Xdebug' &&
semver.valid(initPacket.engineVersion, { loose: true }) &&
semver.gte(initPacket.engineVersion, '3.0.0', { loose: true })
if (
supportedEngine ||
((feat = await connection.sendFeatureGetCommand('resolved_breakpoints')) &&
feat.supported === '1')
) {
await connection.sendFeatureSetCommand('resolved_breakpoints', '1')
}
if (
supportedEngine ||
((feat = await connection.sendFeatureGetCommand('notify_ok')) && feat.supported === '1')
) {
await connection.sendFeatureSetCommand('notify_ok', '1')
connection.on('notify_user', notify => this.handleUserNotify(notify, connection))
}
if (
supportedEngine ||
((feat = await connection.sendFeatureGetCommand('extended_properties')) &&
feat.supported === '1')
) {
await connection.sendFeatureSetCommand('extended_properties', '1')
}
// support for breakpoints
let feat: xdebug.FeatureGetResponse
const supportedEngine =
initPacket.engineName === 'Xdebug' &&
semver.valid(initPacket.engineVersion, { loose: true }) &&
semver.gte(initPacket.engineVersion, '3.0.0', { loose: true })
if (
supportedEngine ||
((feat = await connection.sendFeatureGetCommand('resolved_breakpoints')) &&
feat.supported === '1')
) {
await connection.sendFeatureSetCommand('resolved_breakpoints', '1')
}
if (
supportedEngine ||
((feat = await connection.sendFeatureGetCommand('notify_ok')) && feat.supported === '1')
) {
await connection.sendFeatureSetCommand('notify_ok', '1')
connection.on('notify_user', notify => this.handleUserNotify(notify, connection))
}
if (
supportedEngine ||
((feat = await connection.sendFeatureGetCommand('extended_properties')) &&
feat.supported === '1')
) {
await connection.sendFeatureSetCommand('extended_properties', '1')
}

// override features from launch.json
try {
const xdebugSettings = args.xdebugSettings || {}
await Promise.all(
Object.keys(xdebugSettings).map(setting =>
connection.sendFeatureSetCommand(setting, xdebugSettings[setting])
// override features from launch.json
try {
const xdebugSettings = args.xdebugSettings || {}
await Promise.all(
Object.keys(xdebugSettings).map(setting =>
connection.sendFeatureSetCommand(setting, xdebugSettings[setting])
)
)
)
} catch (error) {
throw new Error(
'Error applying xdebugSettings: ' + (error instanceof Error ? error.message : error)
)
}
} catch (error) {
throw new Error(
'Error applying xdebugSettings: ' + (error instanceof Error ? error.message : error)
)
}

this.sendEvent(new vscode.ThreadEvent('started', connection.id))
this.sendEvent(new vscode.ThreadEvent('started', connection.id))

// wait for all breakpoints
await this._donePromise
// wait for all breakpoints
await this._donePromise

let bpa = new BreakpointAdapter(connection, this._breakpointManager)
bpa.on('dapEvent', event => this.sendEvent(event))
this._breakpointAdapters.set(connection, bpa)
// sync breakpoints to connection
await bpa.process()
let xdebugResponse: xdebug.StatusResponse
// either tell VS Code we stopped on entry or run the script
if (this._args.stopOnEntry) {
// do one step to the first statement
this._hasStoppedOnEntry = false
xdebugResponse = await connection.sendStepIntoCommand()
} else {
xdebugResponse = await connection.sendRunCommand()
let bpa = new BreakpointAdapter(connection, this._breakpointManager)
bpa.on('dapEvent', event => this.sendEvent(event))
this._breakpointAdapters.set(connection, bpa)
// sync breakpoints to connection
await bpa.process()
let xdebugResponse: xdebug.StatusResponse
// either tell VS Code we stopped on entry or run the script
if (this._args.stopOnEntry) {
// do one step to the first statement
this._hasStoppedOnEntry = false
xdebugResponse = await connection.sendStepIntoCommand()
} else {
xdebugResponse = await connection.sendRunCommand()
}
this._checkStatus(xdebugResponse)
} catch (error) {
this.sendEvent(
new vscode.OutputEvent(
`Failed initializing connection ${connection.id}: ` +
(error instanceof Error ? error.message : error) +
'\n',
'stderr'
)
)
disposeConnection()
socket.destroy()
}
this._checkStatus(xdebugResponse)
} catch (error) {
this.sendEvent(
new vscode.OutputEvent((error instanceof Error ? error.message : error) + '\n', 'stderr')
new vscode.OutputEvent(
'Error in socket server: ' + (error instanceof Error ? error.message : error) + '\n',
'stderr'
)
)
this.shutdown()
}
Expand Down

0 comments on commit 85a28a4

Please sign in to comment.