Music, software, life… and stuff.
[ Twitter ] [ GitHub ] [ Linked In ]
I had some fun today upgrading tm_interactive_input.dylib to make it work with Snow Leopard. Previously, it was busted in a pretty decent way.
I can’t be exactly sure, but it seems that malloc() on Snow Leopard calls read() for some strange reason. Since our overloaded read() implementation does quite a few things, including a lot of malloc()ing we have a problem. The end result was that anything loaded with our library injected explodes.
The solution was to use a thread local flag via the pthreads thread local storage to mark when we entered any of our overloaded code paths. This is simple enough, but I couldn’t for the life of me getting working due to a nasty issue which I hadn’t anticipated.
To use the pthread library’s thread local storage stuff, you need to create a token using pthread_key_create() which you can later use to retrieve a thread specific value for. So in C library, how do you handle initialisation code? It turns out that library constructors solve this exact problem.
News to me.
So I initialise the key in a library constructor and litter my code with the appropriate checks and so forth. No dice. I am still seeing the exact same behaviour. To make things more interesting I can’t use GDB because of the nature of the library and I can’t use printf statements because they use malloc() internally which just exacerbates the problem. I can however use write(), so that’s something.
After littering the code with write()s, I discovered that my read() implementation is being called before my library constructor. I don’t know why this is the case but I am guessing that somehow the dynamic linker has made the overloaded functions in our library available to the host binary during the loading process. Either that, or the linker itself is calling our overloaded functions. Either way, kinda strange.
Once I worked out that this was going on, it was trivial to fix. Simply set an ‘initialised’ flag in our library constructor and don’t use our overloaded functions until that is set.
GitHub has the commit for more info, or grab the binary directly (see here for install instructions).
This should be included in the next TextMate distribution.