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
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.
my local path is: C:\Projects\ProcessMaker\3.0.1.8 (from windows explorer),
"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,
"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,
"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
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)