Debugging a Replicant

So, you managed to code yourself a little replicant… only to find it crashing somewhere when dragging it to the Desktop, taking Tracker with it into the abyss.
In this short post, I’d like to spread some tips that were revealed to me by the Grandmaster of the Debugger, Rene “AnEvilYak” himself.

First, before testing your replicant on the Desktop, you should backup the file ~/config/settings/Tracker/tracker_shelf, esp. if you have other replicants already installed, like ActvityMonitor or Workspaces.
If something goes horribly wrong, you can just delete that file.

Now, the trick to debug a replicant, is to have Debugger stop the Tracker when adding the replicant. That way you can set breakpoints at various critical locations in the source, inspect variables and memory and all the rest of it, as usual. Of course, you have to compile your app with debug info for that.

Do this:

  • Start the Debugger.
  • In the Teams window, attach it to Tracker.
  • Open the menu Team | Settings….
  • In there, go to the tab Images and check “Stop when an image is loaded”.
  • You can stop on all images or choose the Type: Custom and add the name of your executable to the list.
  • Close the Settings and drop your replicant onto the Desktop.
  • The Desktop thread will change into the state Debugged.

Now is the time to set those breakpoints:

  • In the tab Images, find your application (should be at the bottom).
  • Selecting the image, you’ll find the source files in a tree in the view to the right (if you have compiled in debug mode).
  • Now set breakpoints by clicking on the grey circles in front of a line of code in the view below.
  • When you’re ready, press the Run button and wait or do stuff in your replicant until a breakpoint is reached.
  • Then do your debugging thing, step through the code examine variables and return values etc. and find your bugs.

Thanks, Rene, for those tips and for that awesome tool of course!

I forgot to mention: There’s a better way to test your replicant than abusing your Desktop/Tracker as testing ground. In Haiku’s trunk you’ll find src/tests/kits/interface/bshelf/ShelfTest.cpp.
Compile it with a simple “g++ -lbe -o Shelf ShelfTest.cpp” and launch the resulting Shelf. It opens a window that you can safely crash all day long by dropping your buggy replicants on it. Just attach Debugger to this instead of Tracker.

You can also use SHelfer for a similar purpose: https://github.com/pulkomandy/shelfer . This one does not save its state, unlike ShelfTest, so you need to re-add your replicant to it everytime you run it.

One more hint to using replicants in general, and esp. when developing one: Replicants find their mother application via its app signature. If you happen to have several executables with that app sig lying around, maybe from the productive app and several different states of debugging for the new release, it’s only by luck your replicant picks the version you want it to…
So, better make sure there’s only one executable with that signature around, maybe by using a special “development” sig.

Probably worth pointing out that this can be a more general booby-trap in Haiku! Anything that uses the signature to locate its executable can tangle you up in the same way. A file with a Preferred App, for example.

This drove me crazy at one point when I was first “Haikuizing” Sequitur. I’d make a change to the source, compile it, and double click the test file I was using… and there’d be no sign of the change! Eventually it dawned on me that the signature was pointing to an older version of the executable.

The pointer to the actual executable to use is in the ‘META:PPATH’ attribute of the signature’s entry in ~/config/settings/mime_db/application. This normally gets set when the app is first activated, and doesn’t automatically change thereafter. (There is also a /boot/system/data/mime_db for packaged apps, but the one in config will override it.)

If you hit such conflict, the easiest solution (if you don’t want to delete the offending version) is to delete the signature’s entry in the mime_db, and then directly activate the desired version of the executable. This should generate an entry with the right META:PPATH.

1 Like

Thanks for the info, Pete! I didn’t know that and I assumed the replicant would find its application with a query for the app-signature…
And it seems it does at least as a fallback.

The pointer to the actual executable to use is in the ‘META:PPATH’ attribute of the signature’s entry in ~/config/settings/mime_db/application. This normally gets set when the app is first activated, and doesn’t automatically change thereafter.

I deleted my app’s entry ~/config/settings/mime_db/application/x-vnd.humdinger-clipdinger, then I duplicated Clipdinger onto the Desktop and restarted Tracker.
The Clipdinger replicant continued to work and a new ~/config/settings/mime_db/application/x-vnd.humdinger-clipdinger was created automatically. Only this time with ‘META:PPATH’ pointing to the copy on the Desktop.
Now I deleted the copy of Clipdinger on the Desktop, restarted Tracker, and again the Replicant kept working and the ‘META:PPATH’ was also updated back to /boot/system/apps/Clipdinger/Clipdinger.

So, ‘META:PPATH’ is being updated, just that in your case, Haiku couldn’t know that you wanted it to open a file with another executable with the same app sig.

I was being a bit sloppy, and left out an important condition…
META:PPATH won’t get automatically updated as long as it is valid. If it’s followed and the target is no longer there, that triggers a new search.

Of course if you have more than one executable with that signature in the system (as I did with Sequitur :slight_smile:) there’s no guarantee the search will end up with the one you expected! [Moral: don’t leave stray versions around…!]