vscode-php-debug: Request making a second request makes it hang

For a project, we have multiple micro services, running in different containers each set up with it’s own xdebug port so I can debug a specific micro service or multiple microservices at once. Everything is working well, breakpoints break, code is able to step properly etc. Unless one microservice makes a call to another one that makes a call back to the first micro service, at which point it hangs until the connection times out.

Before it times out though, in the editor it shows 2 requests on the call stack. If I put a breakpoint in the code in “container A” before the point it makes that call to container B, it breaks just fine. If I then try to step through it, it hangs once it gets to the line that makes the call to container B until the container B call times out, then it continues on with a timeout error creating a stop point in xdebug.

I was able to simplify the error down to a simple test not involving multiple containers or anything, basically just have a call make a curl connection to make a second call.

PHP version: 5.6.30 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": 9002,
			"localSourceRoot": "${workspaceRoot}",
			"serverSourceRoot": "/var/www/public/releases/local_source"
		}
	]
}

XDebug php.ini config:

zend_extension=xdebug.so
[xdebug]
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.remote_connect_back=0
xdebug.remote_mode=req
xdebug.remote_port=9002
xdebug.remote_host=10.55.55.1

XDebug logfile (from setting xdebug.remote_log in php.ini):

Log opened at 2017-05-15 17:02:39
I: Connecting to configured address/port: 10.55.55.1:9002.
I: Connected to client. :-)
-> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/public/releases/local_source/app/webroot/test2.php" language="PHP" xdebug:language_version="5.6.30-1+deb.sury.org~xenial+1" protocol_version="1.0" appid="26056"><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/public/releases/local_source/app/webroot/test2.php -n 10
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="260560003"></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/public/releases/local_source/app/webroot/test2.php" lineno="10" state="enabled" hit_count="0" hit_value="0" id="260560003"></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/public/releases/local_source/app/webroot/test2.php" lineno="10" state="enabled" hit_count="0" hit_value="0" id="260560003"></breakpoint></response>

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

<- run -i 6
Log opened at 2017-05-15 17:02:39
I: Connecting to configured address/port: 10.55.55.1:9002.
I: Connected to client. :-)
-> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/public/releases/local_source/app/webroot/test2.php" language="PHP" xdebug:language_version="5.6.30-1+deb.sury.org~xenial+1" protocol_version="1.0" appid="26052"><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/public/releases/local_source/app/webroot/test2.php -n 10
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="260520005"></response>

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

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

<- breakpoint_list -i 7
-> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="breakpoint_list" transaction_id="7"><breakpoint type="line" filename="file:///var/www/public/releases/local_source/app/webroot/test2.php" lineno="10" state="enabled" hit_count="0" hit_value="0" id="260560003"></breakpoint><breakpoint type="exception" state="enabled" hit_count="0" hit_value="0" id="260560004"></breakpoint></response>

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

Log closed at 2017-05-15 17:02:48

Adapter logfile (from setting "log": true in launch.json):

<- 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 (1:02:39 PM)' } ] } }
-> setBreakpointsRequest
{ command: 'setBreakpoints',
  arguments: 
   { source: 
      { path: '/Users/jonathanfoote/zumba/git/public/app/webroot/test2.php',
        name: 'test2.php' },
     lines: [ 10 ],
     breakpoints: [ { line: 10 } ],
     sourceModified: false },
  type: 'request',
  seq: 4 }
<- setBreakpointsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 4,
  command: 'setBreakpoints',
  success: true,
  body: { breakpoints: [ { verified: true, line: 10 } ] } }
-> 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 }
-> 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 (1:02:39 PM)' } ] } }
new connection 2
<- threadEvent
ThreadEvent {
  seq: 0,
  type: 'event',
  event: 'thread',
  body: { reason: 'started', threadId: 2 } }
<- initializedEvent
InitializedEvent { seq: 0, type: 'event', event: 'initialized' }
-> threadsRequest
{ command: 'threads', type: 'request', seq: 9 }
<- threadsResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 9,
  command: 'threads',
  success: true,
  body: 
   { threads: 
      [ Thread { id: 1, name: 'Request 1 (1:02:39 PM)' },
        Thread { id: 2, name: 'Request 2 (1:02:39 PM)' } ] } }
-> setBreakpointsRequest
{ command: 'setBreakpoints',
  arguments: 
   { source: 
      { path: '/Users/jonathanfoote/zumba/git/public/app/webroot/test2.php',
        name: 'test2.php' },
     lines: [ 10 ],
     breakpoints: [ { line: 10 } ],
     sourceModified: false },
  type: 'request',
  seq: 10 }
-> disconnectRequest
{ command: 'disconnect',
  arguments: { restart: false },
  type: 'request',
  seq: 11 }
<- configurationDoneResponse
Response {
  seq: 0,
  type: 'response',
  request_seq: 7,
  command: 'configurationDone',
  success: true }
<- outputEvent
OutputEvent {
  seq: 0,
  type: 'event',
  event: 'output',
  body: { category: 'console', output: 'connection 1 closed\n' } }
connection 1 closed
<- threadEvent
ThreadEvent {
  seq: 0,
  type: 'event',
  event: 'thread',
  body: { reason: 'exited', threadId: 1 } }
-> setFunctionBreakpointsRequest
{ command: 'setFunctionBreakpoints',
  arguments: { breakpoints: [] },
  type: 'request',
  seq: 12 }

Code snippet to reproduce:

<?php

if (empty($_GET['connect'])) {
	$ch = curl_init('http://localhost/' . $_SERVER['REQUEST_URI'] . '?connect=1');
	curl_exec($ch);
	curl_close($ch);
	die ('end of initial call');
}

phpinfo();

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 18
  • Comments: 41 (19 by maintainers)

Commits related to this issue

Most upvoted comments

Got it working! I’ll make a PR to fix.

So, when you send the run command (or step into, etc), xdebug basically doesn’t do anything on that socket connection until it hits a breakpoint or the next line is run or whatever. So if the code it is running hangs up, say you add a sleep(30) and it runs that line… you won’t get a response until that code is done.

In this scenario described, a new connection is being made during that time it is hung up running PHP code. When there is a new connection, vscode makes requests that basically reset all the breakpoints. But the way it is coded, it attempts to set the breakpoints on ALL connections and it waits for the results of all those calls. For the first connection, it ends up adding those calls to the queue, but it never gets to run them because it’s waiting on that curl request, which is waiting on breakpoint calls… So it gets deadlocked.

🎉 This issue has been resolved in version 1.12.5 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

I suspect my problem might be related to CORS. An additional OPTIONS request is always sent before the actual request so on paper two requests are always made. The issue now is why this is causing the debugger to pause like there is a hidden break-point somewhere instead of ignoring the request and pausing on the actual break-point in the second request.

UPDATE 1: I can confirm this is part of the problem. I started Chrome with the --disable-web-security flag to avoid sending the additional OPTIONS requests, and now the debugger is not pausing when there are no breakpoints, most of the times. There are still occasions where it suddenly stops and there is no solution but to stop the debugger.

UPDATE 2: I am completely guessing here, but to me it seems that the debugger breaks when two requests are made almost simultaneously. This might explain why it breaks when CORS is used, and also why it sometimes works on multiple requests and sometimes it breaks, like I explained in above.

I get a notification for every comment and more comments won’t fix the issue 😉 I don’t have the capacity to look into this and it might not even be a bug in the adapter. If you care about this why not look into it yourself? It’s open source ⭐️

@Zelfapp By the way that sounds like a different issue, this one was a deadlock that happened when one request made a second request, it was not related to multiple ajax requests.

Also this one was resolved and closed over a year ago, you may get more traction creating a new issue or looking for a more recent issue that involves multiple ajax requests.

I see the confusion though if you only read the issue title it does sound related; since you are not the first to comment on it I’ll update the title (if it lets me).

It now hangs when receiving a second Ajax request. My web page sends Ajax requests continuously. Downgraded to version 1.12.4 and now it works great again.

Edit: the following is completely incorrect, keeping it here for posterity and for my own humility.

Looks like a simple configuration change is all that is needed to allow Xdebug to work with multiple sessions. All you need is to set the max_children setting to a high enough value. This is now my launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "pathMappings": {
                "/var/www": "${workspaceRoot}",
            },
            "xdebugSettings": {
                "max_children": 20
            },
        },
    ]
}

The max_children setting seems to mirror a similar setting in PHPStorm mentioned above and it works flawlessly. I can now run Codeception acceptance tests and debug both the test code and the app code at the same time. YAY!

For reference here’s my Xdebug configuration in php.ini:

zend_extension = xdebug.so
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_port = 9000

I forgot that the debug session was already running so I clicked the green play button again (Start Debugging) and now it stopped working. Even when I restart the computer it does’t work anymore. I found the only way to “kind of” make it work is to send and additional request, now the first request will be stopped (but unusable) but I will be able to work with the second request. I will see both request threads in the Call Stack section of the extension. Could not find a way to make it work “normally” again.

image

only one request request is usable, the other is like frozen or something like that.

@RaulGRoque not to be that guy, but please keep the discussions in this repo around this debugger, not PHPStorm. Anyone can use whatever editor they want, but there are folks here (including me) that get notified on every comment and if it’s about configuring PHPStorm then there are forums that are a better place than this ❤️

@jonyo funny but… after computer restart debug works perfectly. What have J done yesterday is J installed node 7.4.0 instead of 8.* and use command npm run compile. Now it works. Thank you @felixfbecker for your support, you are awesome! J’m going back to work, J will test it all day