Vscode-php-debug: Bogus set breakpoint command

Created on 14 Dec 2016  路  9Comments  路  Source: xdebug/vscode-php-debug

The problem seems to be in the breakpoint_set command.

PHP version:
5.6.29-1+deb.sury.org~xenial+1
XDebug version:
2.5.0
Adapter version:
1.10.0

Your launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "localSourceRoot": "Y:\\",
            "serverSourceRoot": "/var/www/html",
            "log": true,
            "stopOnEntry": true
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000
        }
    ]
}

XDebug php.ini config:

root@c678235282db:/var/log/apache2# head /etc/php/5.6/apache2/php.ini
[PHP]
xdebug.remote_enable=1
xdebug.remote_host=192.168.50.113

xdebug.remote_port=9000
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_autostart=true
xdebug.remote_log=/var/log/apache2/xdebug.log

XDebug logfile (from setting xdebug.remote_log in php.ini):
Problem seems to be in the breakpoint_set, somehow much sourceroot seems to have gotten mixed up with the serverRoot

Log opened at 2016-12-14 02:41:02
I: Connecting to configured address/port: 192.168.50.113:9000.
I: Connected to client. :-)
-> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/index.php" language="PHP" xdebug:language_version="5.6.28-1+deb.sury.org~xenial+1" protocol_version="1.0" appid="616"><engine version="2.5.0"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[http://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2016 by Derick Rethans]]></copyright></init>

<- breakpoint_list -i 1
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="1"></response>

<- breakpoint_set -i 2 -t line -f file:///var/www/y:/index.php -n 42
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="6160001"></response>

<- breakpoint_list -i 3
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="3"><breakpoint type="line" filename="file:///var/www/y:/index.php" lineno="42" state="enabled" hit_count="0" hit_value="0" id="6160001"></breakpoint></response>

<- breakpoint_list -i 4
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="4"><breakpoint type="line" filename="file:///var/www/y:/index.php" lineno="42" state="enabled" hit_count="0" hit_value="0" id="6160001"></breakpoint></response>

<- step_into -i 5
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="step_into" transaction_id="5" status="break" reason="ok"><xdebug:message filename="file:///var/www/html/index.php" lineno="27"></xdebug:message></response>

<- stack_get -i 6
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="stack_get" transaction_id="6"><stack where="{main}" level="0" type="file" filename="file:///var/www/html/index.php" lineno="27"></stack></response>

<- context_names -i 7 -d 0
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="context_names" transaction_id="7"><context name="Locals" id="0"></context><context name="Superglobals" id="1"></context><context name="User defined constants" id="2"></context></response>

<- context_get -i 8 -d 0 -c 0
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="context_get" transaction_id="8" context="0"><property name="$compilerConfig" fullname="$compilerConfig" type="uninitialized"></property><property name="$mageFilename" fullname="$mageFilename" type="uninitialized"></property><property name="$mageRunCode" fullname="$mageRunCode" type="uninitialized"></property><property name="$mageRunType" fullname="$mageRunType" type="uninitialized"></property><property name="$maintenanceFile" fullname="$maintenanceFile" type="uninitialized"></property></response>

<- run -i 9
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="run" transaction_id="9" status="stopping" reason="ok"></response>

<- stop -i 10
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="stop" transaction_id="10" status="stopped" reason="ok"></response>

Log closed at 2016-12-14 02:41:43

Adapter logfile (from setting "log": true in launch.json):
Fair warning I had to stitch this together manually because the selection gets cut off when scrolling down the adapter's console pane

<- launchResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 2,
  command: 'launch',
  success: true }
new connection 1
<- threadEvent
ThreadEvent {
  seq: 0,
  type: 'event',
  event: 'thread',
  body: { reason: 'started', threadId: 1 } }
<- initializedEvent
InitializedEvent { seq: 0, type: 'event', event: 'initialized' }
-> threadsRequest
{ command: 'threads', type: 'request', seq: 3 }
<- threadsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 3,
  command: 'threads',
  success: true,
  body: { threads: [ Thread { id: 1, name: 'Request 1 (2:19:50 PM)' } ] } }
-> setBreakpointsRequest
{ command: 'setBreakpoints',
  arguments: 
   { source: { path: 'y:\\index.php', name: 'index.php' },
     lines: [ 42 ],
     breakpoints: [ { line: 42 } ],
     sourceModified: false },
  type: 'request',
  seq: 4 }
<- setBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 4,
  command: 'setBreakpoints',
  success: true,
  body: { breakpoints: [ { verified: true, line: 42 } ] } }
-> setFunctionBreakpointsRequest
{ command: 'setFunctionBreakpoints',
  arguments: { breakpoints: [] },
  type: 'request',
  seq: 5 }
<- setFunctionBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 5,
  command: 'setFunctionBreakpoints',
  success: true,
  body: { breakpoints: [] } }
-> setExceptionBreakpointsRequest
{ command: 'setExceptionBreakpoints',
  arguments: { filters: [] },
  type: 'request',
  seq: 6 }
<- setExceptionBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 6,
  command: 'setExceptionBreakpoints',
  success: true }
-> configurationDoneRequest
{ command: 'configurationDone', type: 'request', seq: 7 }
<- configurationDoneResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 7,
  command: 'configurationDone',
  success: true }
<- stoppedEvent
StoppedEvent {
  seq: 0,
  type: 'event',
  event: 'stopped',
  body: { reason: 'entry', threadId: 1, allThreadsStopped: false } }
-> threadsRequest
{ command: 'threads', type: 'request', seq: 8 }
<- threadsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 8,
  command: 'threads',
  success: true,
  body: { threads: [ Thread { id: 1, name: 'Request 1 (2:19:50 PM)' } ] } }
-> stackTraceRequest
{ command: 'stackTrace',
  arguments: { threadId: 1, startFrame: 0, levels: 20 },
  type: 'request',
  seq: 9 }
<- stackTraceResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 9,
  command: 'stackTrace',
  success: true,
  body: 
   { stackFrames: 
      [ { id: 1,
          name: '{main}',
          source: { name: 'index.php', path: 'Y:\\index.php' },
          line: 27,
          column: 1 } ] } }
-> scopesRequest
{ command: 'scopes',
  arguments: { frameId: 1 },
  type: 'request',
  seq: 10 }
<- scopesResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 10,
  command: 'scopes',
  success: true,
  body: 
   { scopes: 
      [ Scope { name: 'Locals', variablesReference: 1, expensive: false },
        Scope { name: 'Superglobals', variablesReference: 2, expensive: false },
        Scope {
          name: 'User defined constants',
          variablesReference: 3,
          expensive: false } ] } }
-> variablesRequest
{ command: 'variables',
  arguments: { variablesReference: 1 },
  type: 'request',
  seq: 11 }
<- variablesResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 11,
  command: 'variables',
  success: true,
  body: 
   { variables: 
      [ { name: '$compilerConfig',
          value: 'uninitialized',
          type: 'uninitialized',
          variablesReference: 0 },
        { name: '$mageFilename',
          value: 'uninitialized',
          type: 'uninitialized',
          variablesReference: 0 },
        { name: '$mageRunCode',
          value: 'uninitialized',
          type: 'uninitialized',
          variablesReference: 0 },
        { name: '$mageRunType',
          value: 'uninitialized',
          type: 'uninitialized',
          variablesReference: 0 },
        { name: '$maintenanceFile',
          value: 'uninitialized',
          type: 'uninitialized',
          variablesReference: 0 } ] } }
-> continueRequest
{ command: 'continue',
  arguments: { threadId: 1 },
  type: 'request',
  seq: 12 }
<- continueResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 12,
  command: 'continue',
  success: true }
<- threadEvent
ThreadEvent {
  seq: 0,
  type: 'event',
  event: 'thread',
  body: { reason: 'exited', threadId: 1 } }
-> disconnectRequest
{ command: 'disconnect',
  arguments: { restart: false },
  type: 'request',
  seq: 13 }
<- disconnectResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 13,
  command: 'disconnect',
  success: true }

Code snippet to reproduce:

N/A

Most helpful comment

It looks like this is caused by the capitalization of the drive letter in the windows path. Getting rid of the capitalization fixes this issue in a different case (not the one in the OP)

All 9 comments

This definitely looks like a sourceLocalRoot parsing related issue, seems like it's choking up on the naked Y:\\, I moved one file (index.php) to a separate folder and changed my launch.json

and the breakpoints worked as expected...

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "localSourceRoot": "C:\\easy",
            "serverSourceRoot": "/var/www/html",
            "log": true
            //"stopOnEntry": true
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000
        }
    ]
}
Log opened at 2016-12-14 03:17:29
I: Connecting to configured address/port: 192.168.50.113:9000.
I: Connected to client. :-)
-> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/index.php" language="PHP" xdebug:language_version="5.6.28-1+deb.sury.org~xenial+1" protocol_version="1.0" appid="624"><engine version="2.5.0"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[http://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2016 by Derick Rethans]]></copyright></init>

<- breakpoint_list -i 1
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="1"></response>

<- breakpoint_set -i 2 -t line -f file:///var/www/html/index.php -n 42
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="6240001"></response>

<- breakpoint_set -i 3 -t line -f file:///var/www/html/index.php -n 47
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="3" id="6240002"></response>

<- breakpoint_list -i 4
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="4"><breakpoint type="line" filename="file:///var/www/html/index.php" lineno="42" state="enabled" hit_count="0" hit_value="0" id="6240001"></breakpoint><breakpoint type="line" filename="file:///var/www/html/index.php" lineno="47" state="enabled" hit_count="0" hit_value="0" id="6240002"></breakpoint></response>

<- breakpoint_list -i 5
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="5"><breakpoint type="line" filename="file:///var/www/html/index.php" lineno="42" state="enabled" hit_count="0" hit_value="0" id="6240001"></breakpoint><breakpoint type="line" filename="file:///var/www/html/index.php" lineno="47" state="enabled" hit_count="0" hit_value="0" id="6240002"></breakpoint></response>

<- breakpoint_set -i 6 -t exception -x *
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="6" id="6240003"></response>

<- run -i 7
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="run" transaction_id="7" status="break" reason="ok"><xdebug:message filename="file:///var/www/html/index.php" lineno="42"></xdebug:message></response>

<- stack_get -i 8
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="stack_get" transaction_id="8"><stack where="{main}" level="0" type="file" filename="file:///var/www/html/index.php" lineno="42"></stack></response>

<- context_names -i 9 -d 0
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="context_names" transaction_id="9"><context name="Locals" id="0"></context><context name="Superglobals" id="1"></context><context name="User defined constants" id="2"></context></response>

<- context_get -i 10 -d 0 -c 0
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="context_get" transaction_id="10" context="0"><property name="$compilerConfig" fullname="$compilerConfig" type="uninitialized"></property><property name="$mageFilename" fullname="$mageFilename" type="uninitialized"></property><property name="$mageRunCode" fullname="$mageRunCode" type="uninitialized"></property><property name="$mageRunType" fullname="$mageRunType" type="uninitialized"></property><property name="$maintenanceFile" fullname="$maintenanceFile" type="uninitialized"></property></response>

<- run -i 11
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="run" transaction_id="11" status="break" reason="ok"><xdebug:message filename="file:///var/www/html/index.php" lineno="47"></xdebug:message></response>

<- stack_get -i 12
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="stack_get" transaction_id="12"><stack where="{main}" level="0" type="file" filename="file:///var/www/html/index.php" lineno="47"></stack></response>

<- context_names -i 13 -d 0
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="context_names" transaction_id="13"><context name="Locals" id="0"></context><context name="Superglobals" id="1"></context><context name="User defined constants" id="2"></context></response>

<- context_get -i 14 -d 0 -c 0
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="context_get" transaction_id="14" context="0"><property name="$compilerConfig" fullname="$compilerConfig" type="string" size="33" encoding="base64"><![CDATA[L3Zhci93d3cvaHRtbC9pbmNsdWRlcy9jb25maWcucGhw]]></property><property name="$mageFilename" fullname="$mageFilename" type="uninitialized"></property><property name="$mageRunCode" fullname="$mageRunCode" type="uninitialized"></property><property name="$mageRunType" fullname="$mageRunType" type="uninitialized"></property><property name="$maintenanceFile" fullname="$maintenanceFile" type="uninitialized"></property></response>

I am unable to create a failing test case

Unfortunately I just started using VS code yesterday (Should have picked it up much sooner) I have to figure my way around it first before I can debug something like this. Debugging doesn't seem to be as easy as firing up devtools and browsing the scripts

This is the simplest test case that I have that you can test on:

1) find any .php that you know for sure you can break on
2) Move it to C:\
3) change localSourceRoot to C:\\
4) Launch debugger.

You should see a log that looks like this

Log opened at 2016-12-14 04:06:03
I: Connecting to configured address/port: 192.168.50.113:9000.
I: Connected to client. :-)
-> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/index.php" language="PHP" xdebug:language_version="5.6.28-1+deb.sury.org~xenial+1" protocol_version="1.0" appid="617"><engine version="2.5.0"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[http://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2016 by Derick Rethans]]></copyright></init>

<- breakpoint_list -i 1
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="1"></response>

<- breakpoint_set -i 2 -t line -f file:///var/www/c:/index.php -n 42
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="6170004"></response>

<- breakpoint_set -i 3 -t line -f file:///var/www/c:/index.php -n 47
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="3" id="6170005"></response>

Sadly this might be an inherent flaw with the xdebug 2 protocol. In that it claims that setting breakpoints is successful for files that don't exist. I implemented a fix for something like this on the other atom php debug extension that I was using.

The fix does apply in this case as well (simply shows an error message when you try to set a breakpoint on a file that doesn't exist). It simply attempts to source the first line of the file you're trying to break on.

You can take a look https://github.com/gwomacks/php-debug/pull/188/commits/d1fc42d0ca5ac4d58f26876c29db651ac04e69a1

If you don't have the time I can probably try to take look at this over the weekend

I'm talking about the unit test. When I add the exact values to the test, it passes fine.

It looks like this is caused by the capitalization of the drive letter in the windows path. Getting rid of the capitalization fixes this issue in a different case (not the one in the OP)

Hello,

Thank you for your great extension.

Here is my tests regarding this issue.

I get exactly the same behavior when trying to do some remote debug, if I mix the case letters in the localSourceRoot.

example:

my local path is: C:\Projects\ProcessMaker\3.0.1.8 (from windows explorer),

1. if I use it like this in launch.json:

"localSourceRoot": "C:\\Projects\\ProcessMaker\\3.0.1.8\\"

In the xDebug log I will see:

 <- breakpoint_set -i 2 -t line -f c:/Projects/ProcessMaker/3.0.1.8/workflow/public_html/glpi/app.php -n 291
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="29880028"></response>

which is not the right path for the file on the server,

2. but if I set in launch.json:

"localSourceRoot": "c:\\projects\\processmaker\\3.0.1.8\\"

then in the xDebug log I will see:

<- breakpoint_set -i 2 -t line -f file:///L:/inetpub/wwwroot/pm/Projects/ProcessMaker/3.0.1.8/workflow/public_html/glpi/app.php -n 291
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="29880036"></response>

which is not the right path for the file on the server,

3. but if I set in launch.json:

"localSourceRoot": "c:\\Projects\\ProcessMaker\\3.0.1.8\\"

then in the xDebug log I will see:

<- breakpoint_set -i 2 -t line -f file:///L:/inetpub/wwwroot/pm/workflow/public_html/glpi/app.php -n 291
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="29880038"></response>

which is the right path for the file on the server, and the breakpoint will stop execution, and VSC will show the right line in the local file.

@QwertyZW thank you for your workaround.

thank you,
regards,
Tomolimo

Fixed in #245

Was this page helpful?
0 / 5 - 0 ratings

Related issues

johnbillion picture johnbillion  路  6Comments

smuuf picture smuuf  路  10Comments

camrongodbout picture camrongodbout  路  5Comments

andrews05 picture andrews05  路  10Comments

leslieeilsel picture leslieeilsel  路  7Comments