$Id: index.xml 1445 2006-05-04 21:57:43Z slamb $
POSIX thread cancellation (a.k.a. pthread cancellation) is a fairly new feature that so far is implemented extremely badly in most systems. These are a bunch of test programs I've written for checking behavior on different systems and submitting bug reports.
Please note that I'm not sure about all of these tests, so it's possible a platform may have correct behavior and still fail a test. But these test for the behavior my software currently expects. If you disagree with a test, please let me know.
Tested platforms
These are all the platforms I have tested to date:
- Linux + NPTL: I used CentOS 4.2 with kernel-smp-2.6.9-22.0.2.EL and glibc-2.3.4-2.13. (Older glibc releases do not fare as well.)
- LinuxThreads: I tested with the same CentOS 4.2 system with LD_ASSUME_KERNEL=2.4.1 set in the test programs' environment.
- OS X: I tested OS X 10.3.2 Panther.
- HP Tru64 (a.k.a OSF/1, a.k.a Digital UNIX): I used version 5.1B on one of HP's test drive systems.
- HP-UX: I used 11.23 on another HP test drive system.
- FreeBSD: I used 5.1 on another HP test drive system (alpha).
- Solaris: I used Solaris 9 on SPARC with the SUNWspro compiler suite.
- cygwin: I used cygwin 1.5.7-1 on Windows 2000
Test results
| test | Linux + NPTL | LinuxThreads | OS X | Digital Tru64 | HP-UX | FreeBSD | Solaris | cygwin | |
|---|---|---|---|---|---|---|---|---|---|
| Basic functionality | |||||||||
| This basic behavior is absolutely mandated by the Single UNIX Specification version 3. it should pass on every platform. | |||||||||
| cancellation_disable | pass[1] | pass | pass | pass | pass | pass | pass | pass | |
| cancellation_enable | pass | pass | fail | pass | pass | pass | pass | pass | |
| cancellation_returnvalue | pass | pass | fail | pass | pass | pass | pass | pass | |
| C++ behavior | |||||||||
| These are not required by any specification, but are necessary to pass for usable C++ support. C++ should be the language of choice for using thread cancellation, since most code uses exception safety patterns that make cancellation safety trivial. | |||||||||
| cancellation_exception | pass[1] | fail | fail | pass | fail | fail | fail[6] | fail | |
| cancellation_while_throwing | fail | pass[2] | pass[2] | fail | pass[2] | pass[2] | pass[2] | pass[2] | |
| Signal interaction | |||||||||
| These are loosely described by the standards. For code to be able to receive both cancellation requests and signals safely, it should implement kqueue() or pass at least one of these tests. | |||||||||
| cancellation_in_sighandler | fail[3] | fail[3] | fail | fail | fail | fail | fail[3] | fail | |
| siglongjmp_cleanup | fail | fail | fail | fail | fail | fail | fail | fail | |
| ucontext | |||||||||
| The behavior here is not mentioned by the Single UNIX Specification version 3. It is useful for writing cancelable exception-safe C++ code around non-cancelable C libraries such as OpenSSL. See my atoms code for a thorough example. | |||||||||
| swapcontext_before_cleanup | pass | pass | na[4] | pass | pass | fail[8] | pass[7] | na[4] | |
| swapcontext_in_cleanup | pass | pass | na[4] | pass | pass | fail[8] | pass[7] | na[4] | |
| Mandatory cancellation points | |||||||||
| The Single UNIX Specification version 3 specifies a number of mandatory cancellation points; essentially every standardized blocking system call, as it is not possible to use cancellation well without support in these calls. | |||||||||
| cancelpoint_nanosleep | pass | pass | fail | pass | pass | pass | pass | pass | |
| cancelpoint_read | pass | pass | fail | fail[3] | pass | pass | pass | fail | |
| cancelpoint_select | pass | pass | fail | pass | pass | pass | pass | fail | |
| cancelpoint_write | pass | fail | pass[5] | pass | pass | pass | pass | fail | |
[1] - Previous versions failed this test.
[2] - It would be very surprising if this failed, given that this platform does not implement cancellation requests as C++ exceptions.
[3] - This test sometimes passes; the platform contains a race condition.
[4] - This test requires a feature which is not implemented on this platform.
[5] - The write() test on OS X passes, but this is almost certainly a false report caused by the test_cancellation_enable failure.
[6] - Solaris with the -mt compiler option appears to invoke C++ destructors but not catch clauses.
[7] - Solaris/sparc fails to compensate for the stack growing down, but this is easily worked around.
[8] - FreeBSD returns error from getcontext(), before I do anything interesting with cancellation. It appears the ucontext functions are totally broken on FreeBSD/alpha.
Conclusion
Don't use thread cancellation. It doesn't work, and it isn't likely to any time soon. If you need a thread cancellation mechanism, I recommend implementing one with sigsafe rather than using the (poorly) standardized mechanism.
Download
You can download the entire suite of tests here: cancellation-tests-0.1.0.tar.gz.
Copyright © 2003–2005 Scott Lamb <slamb@slamb.org>.