In ImageIO is not thread-safe I reported a problem with ImageIO and threading. I now believe my analysis was wrong, and ImageIO is thread-safe after all. Serializing my ImageIO loading had the effect of hiding the race condition in my own code, so the error became very rare. My apologies to anyone misled by the post, and to anyone at Apple who had to deal with my bug report.
2008-02-27
2008-02-22
ImageIO is not thread-safe
This post is wrong. See ImageIO is thread-safe after all for correction.
I can't find any documentation one way or another, and assumed that as a modern API it was OK to call ImageIO from multiple background threads. It appears that this is not the case. CGCreateImageSourceFromURL fails randomly if you do; always calling it from the main thread appears to work.
Radar 5759067 requests that this preferably be fixed, or if not, at least documented.
2008-02-19
A Delicious Limerick
How does he create all that buzz?
Wil Shipley says "Easy, it's 'cuz
"for Delicious Lib'ry,
"I've the weight of Mike Lee!
"Who says size doesn't matter? It does!"With apologies to Mike (and Wil), and thanks to limerickdb
2008-02-18
Multithreaded libcurl Crash
Thread 0 Crashed:
0 libcurl.4.dylib 0x00391e1c curl_unescape + 78
1 libcurl.4.dylib 0x003929c0 curl_unescape + 3058
2 libcurl.4.dylib 0x00393978 curl_mvsnprintf + 55
3 libcurl.4.dylib 0x003850f9 Curl_failf + 63
4 libcurl.4.dylib 0x0037d8da Curl_resolv + 95
Apparently CURLOPT_NOSIGNAL is very important in multithreaded programs...
2008-02-13
Leopard doesn't verify code signatures?
With all the fuss about code signatures in Leopard, I expected that the system would verify signed applications when they're launched, and prompt the user if the signature is incorrect. It doesn't.
To test this, first verify that TextEdit's signature is valid:
codesign -v /Applications/TextEdit.app/(It should print nothing). Then edit /Applications/TextEdit.app/Contents/Info.plist. Make sure the edit is simple enough that you can undo it — changing the version number is an easy option. Now verify the signature again:
codesign -v /Applications/TextEdit.app/
/Applications/TextEdit.app/: code or signature modifiedNow open TextEdit. It opens without warning. We could have replaced the executable with malicious code, and we wouldn't have been warned.
Make sure you revert your change to Info.plist and re-verify the application.
Since Tiger doesn't have any safeguards of this kind, obviously the situation is no worse than Tiger, but I don't understand what the point of code signing is if the OS doesn't make use of it to make the user's experience that little bit safer.
2008-01-13
CFPreferences keys for OpenGL
Mac OS X's OpenGL framework (only Leopard tested) reads a bunch of values from defaults at app startup. They are:
Integer values
ColorBufferSizeKey
DepthBufferSizeKey
MultisampleKey
RendererIDKey
ThreadedEngineKey
AcceleratedMethodKey
MaxSwapsInFlightKeyBoolean values
ColorBufferSizeEnableKey
DepthBufferSizeEnableKey
VBLSyncEnableKey
MultisampleEnableKey
RendererIDEnableKey
AllowOfflineKeyI haven't been able to make these do anything... anyone know how to use them?
2008-01-03
install_name Magic
Mac OS X application packages allow you to embed frameworks and dynamic libraries within your application, making it easy to comply with the LGPL or use a third-party library without infringing on your users' convenience. However, actually making this work isn't as straightforward as perhaps it should be...
Dynamic libraries (and frameworks, same thing) on Mac OS X include an "install_name". This is the absolute path that the library expects to reside at. When a program is linked, the install_names from any dynamic libraries it links against are copied into the program, and dyld looks for the libraries at these paths when the program is run.
That means that in order to embed a dynamic library into your application bundle, your program must contain an install_name for the library which points to a path inside the application bundle, and the easiest way to get the correct path into your program is to have the correct install_name in the library itself.
Wait, didn't I just say that the install_name is an absolute path? How can it point into the application bundle, when you don't know where the application bundle is? Fortunately there's a special token @executable_path that can appear at the beginning of an install_name that refers to the absolute path of the program loading the library.
Where does all this leave us?
If possible, you'll build your dynamic library with the appropriate install_name
$ gcc foo.c -dynamiclib -o libfoo.dylib -install_name @executable_path/../Libraries/libfoo.dylib
$ otool -L libfoo.dylib
libfoo.dylib:
@executable_path/../Libraries/libfoo.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
Then you'll link your application as normal, and when you put the library in Contents/Libraries everything will just work™
If building the dynamic library appropriately isn't an option (a closed-source third-party library for example), don't worry. It's the install_name copied to your program that's really important, and that can be fudged. You'll link your application with the -headerpad_max_install_names flag, then edit it with install_name_tool.
$ gcc main.c -L. -lfoo -headerpad_max_install_names
$ otool -L a.out
a.out:
/usr/local/lib/libfoo.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
$ install_name_tool -change /usr/local/lib/libfoo.dylib @executable_path/../Libraries/libfoo.dylib a.out
$ otool -L a.out
a.out:
@executable_path/../Libraries/libfoo.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)