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.

Road Trip 2009

Google Earth route of roadtrip
August 18th. Left home late, drove to the border, and on to Fargo. Bought a disposable phone in case we needed it for emergencies etc. (we didn’t) and then on to Montana. We had planned to make it all the way to Billings, MT the first day, but due to leaving late etc. instead planned on staying in Glendive.

Got to Glendive late, and all the hotels were full of road construction workers, so drove on to Miles City. Stayed in Motel 6. It was ok, clean, wifi worked at night, but not in the morning.

August 19th, drove to Pocatello, ID. 531 miles, 9 and a half hours. Drove through the north west corner of Yellowstone park. Lots of roadworks, but it was ok as the scenery was worth looking at.

Stayed at the Best Western Cottontree Inn, very nice room. Internet worked well, good breakfast included.

Next day, drove to Las Vegas. Shannon drove for a hundred miles or so, the only time she drove this trip. The road south from Salt Lake City is extremely boring, nobody bothered going the speed limit, unlike North Dakota, Montana and Idaho, where most drivers seemed to stay at or under it. In fact, Utah, Nevada, California, and Oregon seemed to require speeding.

Arrived at Circus Circus, cheap room, old, internet was $12/day extra (and was incapable, at times, of streaming video from Hulu, or Disney.com). 110F, we walked down the strip a little, too hot. Jessica’s crocs began to melt.

Next day was hotter, we went to Hoover Dam. The tour inside the dam was nice and cool, but outside was almost unbearable. The afternoon and evening were at the pool, or in the Casino.

Another boring drive across the desert to Anaheim. Stayed at another Best Western for three nights. Disneyland, 2 days. Compromise is sometimes necessary.

August 25th – drove to Monterey. Tried to stay on the coast highway, but our GPS (“Nancy the Navigator”) wanted us on the interstate, so we sometimes strayed. Stayed at the Monterey Surf Inn. Very nice room. Internet was acceptable.

August 26th, went to the Monterey Aquarium, it was fantastic. We were there for 3 hours and still missed stuff.

Drove to Boulder Creek for lunch on highway 9. Two beers, hot dog, and 2 burgers and fries for $15. Don’t know how much the new brakes for the minivan will be yet.

Stopped in at Apple and said “Hi”, then drove to San Francisco. We had planned to stay at the Travelodge, but the bulletproof glass, and the police tape put us off (though $39 for a room was tempting), so we stayed at yet another Best Western instead. The free wifi was barely usable, but the room was again, very nice. No free breakfast.

Next day, bought 3 one-day passes for the Muni, and did a few touristy things, rode the streetcar and the cable car, went to chinatown, took a “rocket boat” tour of the bay. We had wanted to visit alcatraz, but the tours were sold out 4 days in advance.

The next day, drove over the Golden Gate bridge, and did the winery thing. Went to Benziger winery and did the tour, tasted some wine, and bought a $40 bottle of Merlot. Then went to Kaz winery, paid $5 and tried 6 wines, bought none. St Francis winery, I did note taste, they thoughtfully provided Jessica with crayons and paper, Shannon tasted everything and bought a $20 bottle of Cabernet Sauvignon. On our way back to the coast we stopped in at Yorkville Cellars and bought a $25 bottle of Malbec.

We drove to Fort Bragg and stayed in the Travelodge. The room was ok, internet was not. One WAP that (speculation) could maybe handle 5 simultaneous clients, and a single residential comcast connection for the entire hotel. Glass beach was interesting the next morning.

Next day continued up the coast to Oregon, and the Pacific Beach resort in Gold Beach. This place also had “free wifi” – as long as you connected to the next door hotel’s access point. Unsurprisingly that was overloaded. Wandered along the beach, looking at driftwood.

Started heading back the next day. Put “Coeur D’Alene” as the destination into the GPS, and it took us over some interesting mountain pass. Shannon was mad (and scared). We did make it all the way, with few stops, and stayed at the Motel 6 in Coeur D’Alene. Hotel wifi was $3/24 hours, but was excellent.

Long drive to Glendive next day. Stayed in another Best Western. Good. Nice breakfast, pool. Glendive is a small place, not a lot there.

Next day, to Grand Forks, and the CanadInn, with the water slide park etc. Jessica enjoyed it. Then a little shopping, and home.

A compressed gps log of the trip is here, if you are so inclined, you can download it, decompress it and load it into google earth.

Photos arehere though we have not uploaded all of them (and I haven’t bothered GPS tagging them).

In case you’re wondering what the heck I was using the hotel wifi for everywhere, it was to plan the next days trip. We did not have much of a plan in advance, and had to figure it out as we went. In some cases (Circus Circus), the hotel did not provide kids TV channels, so we used the internet to watch TV. Also, I can’t go very long without checking my email :)

I released odcctools today, no changes for the last month or so, so I thought I had better put something out there.

http://svn.macosforge.org/repository/odcctools/release/odcctools-20090808.tar.bz2

Due to some recent bus errors, I have been thinking a bit about alignment lately.

When the compiler lays out a struct it will generally ensure that the members of the struct are aligned on the required boundaries for the target architecture. For example, given:

struct foo {
int32_t a;
int16_t b;
};

A compiler may lay it out something like this:

0x??????04 a
0x??????05
0x??????06
0x??????07
0x??????08 b
0x??????09
0x??????0A pad
0x??????0B

The entire struct will likely be placed at an address aligned on a 4 byte boundary because the largest struct member is 4 bytes long, and the int16 type will be followed by a 2 byte pad. Why? So that an array of structs will have the ‘a’ member for all array elements aligned on a 4 byte boundary. All is good, right?

If we add a char to the struct:

struct foo {
int32_t a;
char c;
int16_t b;
};

0x??????04 a
0x??????05
0x??????06
0x??????07
0x??????08 c
0x??????09 pad
0x??????0A b
0x??????0B

Changing our char type to a 64 bit type may result in something like this:

struct foo {
int32_t a;
int64_t c;
int16_t b;
};

0x??????00 a
0x??????01
0x??????02
0x??????03
0x??????04 pad
0x??????05
0x??????06
0x??????07
0x??????08 c
0x??????09
0x??????0A
0x??????0B
0x??????0C
0x??????0D
0x??????0E
0x??????0F
0x??????10 b
0x??????11
0x??????12 pad
0x??????13
0x??????14
0x??????15
0x??????16
0x??????17

In this case (for this imaginary compiler) the entire struct is aligned on an 8 byte boundary, with the 8 byte member also aligned on an 8 byte boundary. So we can still create an array of struct foo, and things will be properly aligned. Of course, even though the individual members of the structure are 4, 8 and 2 bytes long, the entire structure with padding is 24 bytes long, so 10 bytes are “wasted”, it is best to design structs with this in mind, so that my imaginary compiler does not waste space. In the above case, changing the order of the elements is helpful:

struct foo {
int32_t a;
int16_t b;
int64_t c;
};

0x??????00 a
0x??????01
0x??????02
0x??????03
0x??????04 b
0x??????05
0x??????06 pad
0x??????07
0x??????08 c
0x??????09
0x??????0A
0x??????0B
0x??????0C
0x??????0D
0x??????0E
0x??????0F

Now, on some systems a program will run faster if types are aligned “properly”, on others a bus error will occur for misaligned access. Misaligned access will often occur in cases like this:
char array[1024];
...
struct foo * bar = (struct foo *)array;
bar->c = 1;

In the above case, although the array certainly is large enough to hold a foo structure, there is no guarantee that a char will be aligned on an 8 byte boundary, it is a 1 byte type, so there is no need for the compiler to align it. Because of this bar->c = 1; could cause a bus error. OtherĀ  bus errors can occur casting structs of the same size, but with different alignment requirements, etc.

At least firefox works for us on HP-UX now :)

Shantonu noted that for gcc, using -Wcast-align will at least warn about this issue.

Cover of the book Mac for Linux GeeksI was the Technical Reviewer for the book Mac for Linux Geeks, from Apress, Inc. by Tony Steidler-Dennison. It was my first time to be a Technical Reviewer, it was interesting, but not something I plan on repeating, it simply took up too much time, with not enough pay. Getting paid by the page is not a good thing.

This is not a book review, I don’t think that I would be a good reviewer, being biased, as I am. Please find reviews elsewhere – although a quick look at amazon shows none there yet, unfortunately.

[EDIT June 22nd 2009] Found a review here http://hants.lug.org.uk/cgi-bin/wiki.pl?BookReviews/MacForLinuxGeeks. It’s the only one I could find.

« Older entries § Newer entries »