Re: pthread_cancel and cancelation points still broken in Mac OS X 10.5 Leopard?
site_archiver@lists.apple.com Delivered-To: darwin-kernel@lists.apple.com I have filed Bug ID# 5610812 for this issue. Regards, On Nov 22, 2007, at 7:17 PM, Michael Smith wrote: Per, = Mike On Nov 22, 2007, at 2:41 AM, Per Mildner wrote: int read(...) { pthread_testcancel(); return read_nocancel(...); } 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> /* cancel_bug.c */ #include <assert.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> static int exit_status = EXIT_FAILURE; void * func(void *arg) { char buf; int oldstate; ssize_t res; 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; } Regards, _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-kernel mailing list (Darwin-kernel@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-kernel/drivers%40mu.org _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-kernel mailing list (Darwin-kernel@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-kernel/site_archiver%40lists.a... Sorry if this was the wrong forum for this question, it was not intended as a complaint or bug report. I hoped some kernel hacker would be able to shed some light on the technical background to the implementation of this new and important feature. Whilst your complaint may well be legitimate, this is not a bug- reporting forum. Please file a bug (bugreporter.apple.com) and include the bug number when discussing the matter here or (ideally) in any other forum. 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#t... 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: 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. This is with Xcode 3.0. Compiling with -D_APPLE_C_SOURCE does not make a difference. #define CHECK(X) do { if ((X) == 0) { fprintf(stderr, "%s:%d CHECK FAILED\n", __FILE__, (int)__LINE__); } } while (0) 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); So, has Apple and the Open Group conformance testers made a huge mistake or am I missing something? This email sent to drivers@mu.org This email sent to site_archiver@lists.apple.com
participants (1)
-
Per Mildner