driftphp / server

:cyclone: ReactPHP based non-blocking server
https://driftphp.io
MIT License
68 stars 14 forks source link

When running the server with watch argument breakpoints doesn't work using xdebug #89

Open nivpenso opened 3 years ago

nivpenso commented 3 years ago

This is an issue I found while setting up a development environment.

I haven't explored the issue furthermore, and for that reason, I find it important to add this issue here for further investigation.

When setting debug configuration settings (I use PHPStorm) to run a server with a watch argument, the server doesn't pause on breakpoints except at the bootstrap.php file.

Important note: the same configuration with a run argument works and the program pause at breakpoints.

image

nivpenso commented 3 years ago

So after a quick investigation, it seems that the issue is not in the server. it comes from react/child-process which is used by php-watcher.

The main issue is that the xdebug can't attach to a forked process - I'm not sure why not but it is what it is and I didn't continue it further.

here is a quote from the Gitter page of ReactPHP image

mmoreram commented 3 years ago

Amazing research :D Thanks!

The thing here is that I don't really find an alternative of using child-process for the php-watcher. We could continue this discussion there. WDYT?

nivpenso commented 3 years ago

So the way I see it the main problem here is that there is an issue with xdebug to communicate with a fork of a child-process.

The question is why do we use a forked process from the first place? (generally speaking, I don't really like this approach, it is not consistent between different OS types and can cause memory and resource leaks) I assume that the answer is to respawn the server's process on filesystem change events - which is a reasonable approach.

Maybe instead of respawning the server's process, we could use only one process which will do both:

  1. track fs change events
  2. Act as HTTP webserver. Once a filesystem change event will fire, the kernel gets rebooted.

In order to achieve that, we would need the ability to re-boot the kernel on-demand in a running process. I'm not sure if the kernel supports such functionality but if so, I believe it will work.

Let me know what do you think

nivpenso commented 3 years ago

some updates:

  1. it is possible to use libuv in order to watch files and paths. This lib is well-known (also used by NodeJS) and utilizes filesystem APIs to track changes, which in my opinion can improve performance. The question is how to integrate it with the ReactPHP loop (since we can't have too event loops in the same process)

  2. In terms of kernel rebooting - it seems that the kernel does have the ability to reboot itself which is good

  3. (New question) Should the loop get be restarted or not (meaning that any existing task in the loop should be aborted)? or maybe even reinitiate the HttpServer instance?

nivpenso commented 3 years ago

some updates:

Good news! reactphp by default checks (in EventLoopFactory::create()) whether the libuv is installed and if it is, it uses libuv as the async event-loop implementation. Since the libuv already implemented file and path watchers we can utilize it.

It means that the part of integrating the watcher within the same process of the HTTP-server is feasible and we can avoid using php-watcher

Please note: on PHP environments with no ext-uv installed we can go with the php-watcher fallback that will create a new child-process but won't allow debugging and print a recommendation message to install libuv extension.

@mmoreram Let me know what do you think about it?