My tests indicate that pthread_cancel still cannot interrupt blocking
system calls like read(2) in Intel Mac OS X 10.5.1, despite the claim
that it is now UNIX 2003 compliant. A brief look at the Darwin 9.0
kernel sources seems to confirm this.
The Single Unix Specification v3 (SUSv3) defines cancelation points in
http://www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_09.html#tag_02_09_05_02
The critical part, and the reason why pthread_testcancel is not
sufficient is "If a thread has cancelability enabled and a
cancellation request is made with the thread as a target while the
thread is suspended at a cancellation point, the thread shall be
awakened and the cancellation request shall be acted upon.". That is,
pthread_cancel should wake (a well defined list of) blocking system
calls.
The below test program shows that a blocking read() is _not_ awakened
by pthread_cancel, making the cancelation handling in Leopard no
improvement over earlier OS releases and in violation of the SUSv3
standard.
The test program starts a worker thread that loops reading from
standard input. The main thread then sleeps for a while to ensure that
the worker thread has blocked in read(2) and the main thread then
cancels the worker thread. This program terminates on Linux and
Solaris but not on Intel Leopard 10.5.1.
From a cursory glance at xnu-1228, e.g. sys_generic.c, it looks as if
the system calls that SUSv3 requires to be cancelation points are all
implemented something like the following template:
int read(...) {
pthread_testcancel();
return read_nocancel(...);
}
That is, if a cancel is pending when the system call is entered then
the call will be canceled but once the real system call is blocking it
will not react to cancel requests.
Transcript:
bash$ gcc cancel_bug.c -Wall && ./a.out
Created thread, sleeping
calling read..<press return>
.called read()==1
calling read..<press return>
.called read()==1
calling read..cancelling read()
<blocks forever or until more input is available>
This is with Xcode 3.0. Compiling with -D_APPLE_C_SOURCE does not make
a difference.
/* cancel_bug.c */
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int exit_status = EXIT_FAILURE;
#define CHECK(X) do { if ((X) == 0) { fprintf(stderr, "%s:%d CHECK
FAILED\n", __FILE__, (int)__LINE__); } } while (0)
void *
func(void *arg)
{
char buf;
int oldstate;
ssize_t res;
exit_status = EXIT_SUCCESS;
/* redundant */
CHECK(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate) == 0);
/* Will not terminate unless cancelled or read error */
do
{
fprintf(stderr, "calling read..");fflush(stderr);
res = read(STDIN_FILENO, &buf, 1);
fprintf(stderr, ".called read()==%ld\n", (long)res);fflush (stderr);
}
while (res != -1);
return NULL;
}
int
main(void)
{
pthread_t thread;
void *retval;
CHECK(pthread_create(&thread, NULL, func, NULL) == 0);
fprintf(stderr, "Created thread, sleeping\n");fflush(stderr);
sleep(10); /* ensure thread reaches blocking read */
fprintf(stderr, "cancelling read()\n");fflush(stderr);
CHECK(pthread_cancel(thread) == 0);
CHECK(pthread_join(thread, &retval) == 0);
CHECK(PTHREAD_CANCELED == retval);
return exit_status;
}
So, has Apple and the Open Group conformance testers made a huge
mistake or am I missing something?
Regards,
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden