Snow Leopard and offlineimap

Yesterday tjcarter was complaining in #fink about offlineimap not working on Snow Leopard, so last night I thought I’d take a look.

Indeed, it doesn’t work, and the reason is that ‘import locale’ is being called on a thread, which loads _locale.so, which requires that the CoreFoundation framework also be loaded. A simple reproducer in python is:

import os, sys
import threading
class Foo(threading.Thread):
	def __init__(self):
		threading.Thread.__init__(self)
	def run(self):
		import locale

t = Foo()
t.start()

The CoreFoundation framework must be loaded on the “main” thread, its initialization expects that, if it is loaded on some other thread, then it causes the application to exit rather abruptly. You can reproduce the same thing easily in C with:

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void* do_open(void* unused) {
        void * handle = dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_GLOBAL);
        if (! handle) fprintf(stderr,"ERROR: %s\n",dlerror());
        pthread_exit(NULL);
}

int main() {
        pthread_t t;
        pthread_attr_t a;
        if (pthread_attr_init(&a)) exit(1);
        if (pthread_create(&t,&a,do_open,NULL)) exit(2);
        pthread_attr_destroy(&a);
        sleep(5);
        return 0;
}

The failure can be avoided/worked around by ensuring that CoreFoundation is loaded on the main thread. For offlineimap, a simple way to do this is to put ‘import locale’ in the main script before init.startup is run. This will load _locale.so and thus CoreFoundation. CoreFoundation will run its initializers, and all will be well.

I am pretty sure that I have seen it documented somewhere that Apple’s frameworks must be loaded on the main thread, but I don’t seem to be able to find that documentation this morning (perhaps I just need more coffee?). In any case, loading any libraries that you need at application startup before you go spinning off threads is, in my opinion, a reasonable solution.