PTHREAD_CANCEL_DEFERRED

Kostik Belousov kostikbel at gmail.com
Thu Aug 12 08:30:14 UTC 2010


On Thu, Aug 12, 2010 at 10:59:57AM +0000, David Xu wrote:
> Kostik Belousov wrote:
> >Hi,
> >Let consider the thread in the state where the cancelation is enabled
> >and cancelation mode set to the PTHREAD_CANCEL_DEFERRED.
> >
> >SUSv4 says the following:
> >Whenever a thread has cancelability enabled and a cancellation request
> >has been made with that thread as the target, and the thread then
> >calls any function that is a cancellation point (such as
> >pthread_testcancel() or read()), the cancellation request shall be
> >acted upon before the function returns. 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.
> >
> >Take the close(2) as example, and assume that the cancel is enabled
> >for the thread in deferred mode. libthr wrapper around the syscall
> >executes this:
> >
> >     	curthread->cancel_point++;
> >	testcancel(curthread);
> >	__sys_close(fd);
> >	curthread->cancel_point--;
> >
> >The pthread_cancel() sends the SIGCANCEL signal to the
> >thread. SIGCANCEL handler calls pthread_exit() if thread has the
> >cancel_point greater then 0.
> >
> >I think this is not right. For instance, thread can be canceled due to
> >SIGCANCEL delivery at the point after the return into the usermode
> >from close(), but before cancel_point is decremented. IMO, the cited
> >statements from the SUSv4 prohibit such behaviour. We should cancel
> >either before closing fd, or during the sleep in close(), but then the
> >syscall should be aborted ("as if signal is delivered"), and again fd
> >should not be closed.
> >
> >Actually, besides not being compliant, I think that the current
> >behaviour is not useful, since in deferred case, we cannot know
> >whether the action by the call that is cancelation point was performed
> >or not.
> >
> >This is not a rant, I probably will fix the issue if it is agreed
> >upon. Opinions ?
> 
> it is true that a cancellation point does not return when cancellation
> happens, so we really does not know if it did something or not,
> and SUSv4 does not say cancellation point is an atomic transaction,
> and whether it will rollback when cancellation happens, the problem may
> happen even if you want to fix it, if the cancellation request is sent
> after int 0x80 instruction returns (on i386) but before libc close()
> stub returns, the cancellation still can happen, so could you tell
> if the file handle is closed or not ? there is no way to tell
> caller that the close() really did something.
> I found the issue when I wrote the code, and it seems Linux does
> it in same way, so I had not done further work on it.

What I am proposing is to not cancel if close() indeed closed the
descriptor. The same could be done for all other cancelation points that
are syscalls.

I evaluated the possible implementation. It looks like it is enough,
when thread is switched to cancel enabled and deferred mode, to make
SIGCANCEL delivery special. Namely, it should be only delivered at the
cancelable syscall _entry_ point and on syscall return when error is
EINTR or ERESTART. pthread_testcancel() is also becoming a dummy syscall,
with the same rules of SIGCANCEL delivery.

Cancelable syscalls would be marked in the syscall table, the cost of
the change is that pthread_setcanceltype() becomes a syscall.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-threads/attachments/20100812/813e91f4/attachment.pgp


More information about the freebsd-threads mailing list