Milestone
Weekly reports are slowly turning into fortnightly reports, heh. But despite this I'm satisfied with the progress. During this time I managed to finish gdb-js
, write documentation for it, publish it on npm and set up CI. Also, I fixed the ws-streamify
and puzzled out the debugging of multithreaded and multi-process'ed targets in GDB and added the corresponding examples to gdb-examples
repo. But what's more important — I've finally acquired a good understanding of how the project should be implemented. And in the meantime I've passed another exam :D But let's see it in a little more detail.
Multithreading
Honestly, I hate multithreading :D Except maybe its application to pure functional languages. But for everything else it just sounds scary to me. Deadlocks, unobvious control flow... That's why I like event-loop. And that's why I deliberately avoided this topic while I was writing gdb-js
. But it couldn't be postponed forever, so I created a simple yet handy example of multithreaded program for gdb-examples
repo: multiple ticket-sellers sell tickets simultanously until there's no tickets remain. And while playing with it in GDB I understood that non-stop
and target-async
modes are must have in a GDB frontend. So i included them in gdb-js
and then added thread
argument to all of the methods where it makes sense. That's it.
Multiple targets
First off, I read how it works in Chromium and then how it's coming to Firefox. From these articles I understood how important it is to have a multi-process architecture and thus it's neccessary to have the ability to debug it. However, unlike threads when a process is created it's not attached to GDB automatically. The exception to this is only systems that support fork
and vfork
. On other systems (e.g. Windows) I believe it should be done manually. But even in this case it seems that it's not that straight-forward. So I decided to just add methods for attaching and detaching processes to gdb-js
and a method that disables detach-on-fork
mode, so that forks will be attached automatically. Also, I've created the example of a program with multiple processes (multiple counters) and pushed it to gdb-examples
repo.
Python and CLI commands
In previous post I said that MI interface is lacking some commands. But GDB allows to use CLI commands in MI mode with -interpreter-exec console
. The only problem with it is getting the results. So I decided to make use of Python and its function gdb.execute("<CLI command>", False, True)
. In GDB >= 7.3 it has a third argument which when True
returns a string with results of CLI command execution. So I wrapped it into an useful command concat
which executes given CLI command, adds a given prefix to the results of command execution and prints this in a single MI console record. Also, I've created a command info context
which takes all variables (globals, static, locals) in the current context and prints a nice JSON. However, getting all (I mean, ALL) globals for the current target is only possible with manually parsing of its symbol table. So I just decided to write one another pegjs parser for the results of info variables
command. It all works pretty well. Besides we now have a nice infrastructure to add new functionality to GDB without even bothering the server. However, scripts can be (from my experience) only ~3700 symbols long. Maybe it makes sense to make use of pyminifier
. To summarize, this is how I manage the results handling now, it's an exact copy of the actual flow in the code (I sooo love streams):
gdb-js
Here's Travis CI. Here's the npm package. Here's the documentation. I considered several documentation generators, but then just decided to use JSDoc. Although I also like Docco and its literate programming philosophy.
react-gdb
Finally, the most important part. Thanks to @jonasf I finally realized the core goals that the project is pursuing and how it should be implemented to fit these goals. Back then I thought that react-gdb
is just a static site that needs a link to the WebSocket server to work. This made me think that react-gdb
is something that has dependency on the server (and its protocol, of course). But in fact, it's just a React component that can have a much simpler interface (almost the same as gdb-js
has). It can accept a child process (e.g. an instance of docker-exec-websocket-server
), source provider and (optionally) debug log provider. Source provider can be implemented as a plain function that accecpts a file name and returns the sources of this file (for Firefox, it can be a hg repository provider, for example). This interface will make react-gdb
absolutely server-agnostic, agnostic about the location of sources and reusable. So, that's it. By the way, I've also put a lot of thought on how the UI should look like when I add multithreading and multiple targets support to it. I've ended up with something similar to NetBeans approach (with the amendment that I want to group threads by a process):
P.S.
- As for
ws-streamify
it now merges the buffers into one message when it's possible. - I've spent some time on improving my vim workflow with a bunch of useful plugins and now I regret not doing it earlier т_т.
- I have an exam on 24th of June. So, I will continue my work on the project after it.