Flow control commands should not evaluate the conditions of conditional breakpoints when enabling and disabling breakpoints during stepping. Also, all breakpoints, rather than just the first matching breakpoint should be enabled/disabled.
A client couldn't break execution during eval. There used to be a lot of barriers to making that right, but I fixed most of them with a previous diff on unifying client-side event loops. Now the only barrier was that a server-side thread processing an interrupt was blocking the signal polling thread by holding a mutex while processing the interrupt. Changed to set a flag to disable polling when starting to process the interrupt (and unsetting it when done), while still synchronizing with the signal polling thread to ensure only one thread is sending the client messages at a time. Added logic to re-enable polling while executing PHP for eval, print, etc. Plumbed the proxy thru to the point where we check the clause on conditional breakpoints, too, since that's the third (and final) place we do this.
Added some test cases. Also now permit caller=>func() type of breakpoints. To make this work, I added a method, getCallingSite, to class InterruptSite and use this to walk the stack when checking if a site matches a break point that has more than one function name.
Currently a breakpoint specified as relativefilepath:lineno will match only if the relative file path is a simple file name or if sandbox root + relative file path is an exact match. This is now generalized so that matching occurs if the relative file path is a suffix (path) of the absolute path of the execution location.
The debugger client now accepts feedback from the the debugger server about whether a breakpoint can be hit, absent further loads of files, classes or functions.
Small stepping, which is stepping over sub-expressions (kinda), worked but was a little goofy. The mode was set on the client, passed over with control flow commands, placed on the execution context, then retrieved from there and used by those same flow commands. Removed the execution context part of it, since it was useless, and factored grabbing the offsets into the flow cmds where they belong instead of doing it all the time.
The run cmd also had some notion of small stepping, but you'll note it was never sent over the wire. Nuked that, since it never mattered anyway.
We had two similar-but-different functions for getting a notification from the VM about an exception. Cleaned that up by using the proper one for a thrown exception where appropriate, and moving the old one into a hook (like the other VM->debugger hooks) specifically for error messages.
There were multiple issues with flow control when exceptions occur. Fixed these by ditching the reliance on the exception thrown interrupt and introduce an exception handler interrupt, which indicates control is about to pass to a catch clause. This gives us much better insight into how execution is flowing and how we might need to adjust an in-flight stepping operation.