Some years back, I worked on bringing basic debug support to Rakudo Perl 6. It works by taking the program AST and instrumenting it. This approach produced a somewhat useful result, but also carries a number of limitations:
- It required all code that is to be debugged to be recompiled, which gets slow when there are many modules – especially since there isn’t a way to cache this debug version. Back when I wrote it, all Perl 6 programs were pretty small. Today, larger systems are being built, with more significant module dependency chains.
- It caused a fairly significant slowdown to the code that was being debugged.
- It wasn’t useful to Rakudo core developers, and less useful than would be ideal for Perl 6 power users, as it could not debug into the built-ins and compiler. It’s great that so much of Perl 6 is written in Perl 6, but that was sadly off-limits for the existing debugger. There wasn’t much we could easily do to address that, either.
- There wasn’t any way to debug remotely. Technically, we probably could have built this, as the debugger had pluggable frontends. However, to my knowledge, the only one ever written was the CLI (Command Line Interface) that exists to this day.
- That CLI never learned to deal with threads. Given one of Perl 6’s selling points is its concurrency support, that’s a significant limitation.
At Edument, the company where I work, we’re keen to support Perl 6 and drive it forward. Last summer, we released Cro. In the autumn, we started work on our next Perl 6 product – which we’ll be announcing in just a couple more weeks. Along the way, we realized that it really needed Perl 6 to have a better debugging solution. So what did we do?
We decided to pitch in and fund its development, of course! During the winter, we’ve worked on adding remote debug support to MoarVM, and today we’ve opened a pull request with it.
With our additions, MoarVM can be started with a flag indicating it should run a debug server, along with a port that it should listen on. It can then either wait for a connection before doing anything, or run the program as normal but allow for a connection to be made later.
The debug protocol is defined in terms of MessagePack, which you can think of as being like a binary form of JSON. The PR includes documentation of the protocol, and we hope that having based it on an existing serialization format will make implementation of that easy for those who should wish to do so.
The implemented features available through the protocol include:
- Suspending and resuming all threads, or individual threads
- Enumerating threads and, when they are suspended, getting their stack traces
- Reading the lexical variables of a callframe
- Setting breakpoints and getting notified if they are hit (and, optionally, suspending execution)
- Fetching object attributes, array elements, and hash keys/values
We’ve more plans for the future, but this is already a quite decent feature set that opens up a lot of possibilities.
Along with the debug server implementation in MoarVM, we’re also releasing a Perl 6 module that speaks the debug protocol, along with a basic, but useful, command line application built using it. These aren’t things that we directly needed, but we hope the CLI will be useful (and, of course, contributions are welcome – I’m sure I’ll be patching it some), and that the library will pave the way for further interesting tools that might be built in terms of the debug protocol.
All being well, the next MoarVM release will include remote debug support. With time, this will lead to much better debugging support for Perl 6, to keep pace with the growing size and concurrent nature of applications people are building in Perl 6 today. Enjoy!