Friday, April 25, 2014

Debugging library loads in OS X using dtrace

When your OS X app starts to get a little bigger and a little complicated, you may encounter some issues with library loading. Getting the correct libraries to load is not always easy and in our case, where we develop a Python app and need to use a different Python version than what's on the system, even more trouble is added to the mix. Sometimes the system Python library sneaks in and our poor app then crashes with a sad message

Fatal Python error: Interpreter not initialized (version mismatch?)

or, alternatively, with an even more sad message saying

Fatal Python error: PyThreadState_Get: no current thread

These are caused by mixing two different Python library versions in the same process. They step on each other memory structures and don't play along nicely. Need to separate them.
But how can you quickly figure out which of your modules is referencing the wrong Python library? Use dtrace. I already wrote a post about how useful this tool can be. And we can employ it for this task as well. On OSX, it comes with a nice GUI app called Instruments (a part of XCode package). In this app, click the Instrument menu and select Build New Instrument... You will see the following window and now you need to fill in the details as below. In principle, you'll put a break/tracepoint on the function dlopen in libdyld.dylib and tell the system to record the stack trace in that moment as well as the first function argument which is the path to the library to be loaded.

When you set this up, add the new instrument to your current project and select the program to instrument. You can attach to an already running process or start a new instance. The result will look like the image below. You can see the library load events together with the path argument and for each item you can see the call stack on the right.
Awesome! Now let's get some ice cream.

No comments:

Post a Comment