Standards, Environments, and Macros cancellation(5)
NAME
cancellation - overview of concepts related to POSIX thread
cancellation
DESCRIPTION
FUNCTION ACTION
pthreadcancel() Cancels thread execution.
pthreadsetcancelstate() Sets the cancellation state of a thread.
pthreadsetcanceltype() Sets the cancellation type of a thread.
pthreadtestcancel() Creates a cancellation point in the cal-
ling thread.
pthreadcleanuppush() Pushes a cleanup handler routine.
pthreadcleanuppop() Pops a cleanup handler routine.
Cancellation
Thread cancellation allows a thread to terminate the execu-
tion of any application thread in the process. Cancellation
is useful when further operations of one or more threads are
undesirable or unnecessary.
An example of a situation that could benefit from using can-
cellation is an asynchronously-generated cancel condition
such as a user requesting to close or exit some running
operation. Another example is the completion of a task
undertaken by a number of threads, such as solving a maze.
While many threads search for the solution, one of the
threads might solve the puzzle while the others continue to
operate. Since they are serving no purpose at that point,
they should all be canceled.
Planning Steps
Planning and programming for most cancellations follow this
pattern:
1. Identify which threads you want to cancel, and
insert pthreadcancel(3C) statements.
2. Identify system-defined cancellation points where a
thread that might be canceled could have changed
system or program state that should be restored.
See the Cancellation Points for a list.
3. When a thread changes the system or program state
just before a cancellation point, and should
restore that state before the thread is canceled,
place a cleanup handler before the cancellation
point with pthreadcleanuppush(3C). Wherever a
SunOS 5.11 Last change: 4 Oct 2005 1
Standards, Environments, and Macros cancellation(5)
thread restores the changed state, pop the cleanup
handler from the cleanup stack with
pthreadcleanuppop(3C).
4. Know whether the threads you are canceling call
into cancel-unsafe libraries, and disable cancella-
tion with pthreadsetcancelstate(3C) before the
call into the library. See Cancellation State and
Cancel-Safe.
5. To cancel a thread in a procedure that contains no
cancellation points, insert your own cancellation
points with pthreadtestcancel(3C). This function
creates cancellation points by testing for pending
cancellations and performing those cancellations if
they are found. Push and pop cleanup handlers
around the cancellation point, if necessary (see
Step 3, above).
Cancellation Points
The system defines certain points at which cancellation can
occur (cancellation points), and you can create additional
cancellation points in your application with
pthreadtestcancel().
The following cancellation points are defined by the system
(system-defined cancellation points):
creat(2)aiosuspend(3C), close(2), creat(2), getmsg(2),
getpmsg(2), lockf(3C), mqreceive(3C), mqsend(3C),
msgrcv(2), msgsnd(2), msync(3C), nanosleep(3C), open(2),
pause(2), poll(2), pread(2), pthreadcondtimedwait(3C),
pthreadcondwait(3C), pthreadjoin(3C),
pthreadtestcancel(3C), putmsg(2), putpmsg(2), pwrite(2),
read(2), readv(2), select(3C), semwait(3C), sigpause(3C),
sigwaitinfo(3C), sigsuspend(2), sigtimedwait(3C),
sigwait(2), sleep(3C), sync(2), system(3C), tcdrain(3C),
usleep(3C), wait(3C), waitid(2), wait3(3C), waitpid(3C),
write(2), writev(2), and fcntl(2), when specifying FSETLKW
as the command.
When cancellation is asynchronous, cancellation can occur at
any time (before, during, or after the execution of the
function defined as the cancellation point). When cancella-
tion is deferred (the default case), cancellation occurs
only within the scope of a function defined as a cancella-
tion point (after the function is called and before the
function returns). See Cancellation Type for more informa-
tion about deferred and asynchronous cancellation.
SunOS 5.11 Last change: 4 Oct 2005 2
Standards, Environments, and Macros cancellation(5)
Choosing where to place cancellation points and understand-
ing how cancellation affects your program depend upon your
understanding of both your application and of cancellation
mechanics.
Typically, any call that might require a long wait should be
a cancellation point. Operations need to check for pending
cancellation requests when the operation is about to block
indefinitely. This includes threads waiting in
pthreadcondwait() and pthreadcondtimedwait(), threads
waiting for the termination of another thread in
pthreadjoin(), and threads blocked on sigwait().
A mutex is explicitly not a cancellation point and should be
held for only the minimal essential time.
Most of the dangers in performing cancellations deal with
properly restoring invariants and freeing shared resources.
For example, a carelessly canceled thread might leave a
mutex in a locked state, leading to a deadlock. Or it might
leave a region of memory allocated with no way to identify
it and therefore no way to free it.
Cleanup Handlers
When a thread is canceled, it should release resources and
clean up the state that is shared with other threads. So,
whenever a thread that might be canceled changes the state
of the system or of the program, be sure to push a cleanup
handler with pthreadcleanuppush(3C) before the cancella-
tion point.
When a thread is canceled, all the currently-stacked cleanup
handlers are executed in last-in-first-out (LIFO) order.
Each handler is run in the scope in which it was pushed.
When the last cleanup handler returns, the thread-specific
data destructor functions are called. Thread execution ter-
minates when the last destructor function returns.
When, in the normal course of the program, an uncanceled
thread restores state that it had previously changed, be
sure to pop the cleanup handler (that you had set up where
the change took place) using pthreadcleanuppop(3C). That
way, if the thread is canceled later, only currently-changed
state will be restored by the handlers that are left in the
stack.
SunOS 5.11 Last change: 4 Oct 2005 3
Standards, Environments, and Macros cancellation(5)
The pthreadcleanuppush() and pthreadcleanuppop() func-
tions can be implemented as macros. The application must
ensure that they appear as statements, and in pairs within
the same lexical scope (that is, the pthreadcleanuppush()
macro can be thought to expand to a token list whose first
token is '{' with pthreadcleanuppop() expanding to a token
list whose last token is the corresponding '}').
The effect of the use of return, break, continue, and goto
to prematurely leave a code block described by a pair of
pthreadcleanuppush() and pthreadcleanuppop() function
calls is undefined.
Cancellation State
Most programmers will use only the default cancellation
state of PTHREADCANCELENABLE, but can choose to change
the state by using pthreadsetcancelstate(3C), which deter-
mines whether a thread is cancelable at all. With the
default state of PTHREADCANCELENABLE, cancellation is
enabled and the thread is cancelable at points determined by
its cancellation type. See Cancellation Type.
If the state is PTHREADCANCELDISABLE, cancellation is dis-
abled, the thread is not cancelable at any point, and all
cancellation requests to it are held pending.
You might want to disable cancellation before a call to a
cancel-unsafe library, restoring the old cancel state when
the call returns from the library. See Cancel-Safe for
explanations of cancel safety.
Cancellation Type
A thread's cancellation type is set with
pthreadsetcanceltype(3C), and determines whether the thread
can be canceled anywhere in its execution or only at cancel-
lation points.
With the default type of PTHREADCANCELDEFERED, the
thread is cancelable only at cancellation points, and then
only when cancellation is enabled.
If the type is PTHREADCANCELASYNCHRONOUS, the thread is
cancelable at any point in its execution (assuming, of
course, that cancellation is enabled). Try to limit regions
of asynchronous cancellation to sequences with no external
dependencies that could result in dangling resources or
unresolved state conditions. Using asynchronous cancellation
SunOS 5.11 Last change: 4 Oct 2005 4
Standards, Environments, and Macros cancellation(5)
is discouraged because of the danger involved in trying to
guarantee correct cleanup handling at absolutely every point
in the program.
Cancellation Type/State Table
Type State
Enabled (Default) Disabled
Deferred (Default) Cancellation All cancellation
occurs when the requests to the
target thread target thread are
reaches a cancel- held pending.
lation point and a
cancel is pending.
(Default)
Asynchronous Receipt of a All cancellation
pthreadcancel() requests to the
call causes target thread are
immediate cancel- held pending; as
lation. soon as cancella-
tion is re-
enabled, pending
cancellations are
executedimmedi-
ately.
Cancel-Safe
With the arrival of POSIX cancellation, the Cancel-Safe
level has been added to the list of MT-Safety levels. See
attributes(5). An application or library is Cancel-Safe
whenever it has arranged for cleanup handlers to restore
system or program state wherever cancellation can occur. The
application or library is specifically Deferred-Cancel-Safe
when it is Cancel-Safe for threads whose cancellation type
is PTHREADCANCELDEFERED. See Cancellation State. It is
specifically Asynchronous-Cancel-Safe when it is Cancel-Safe
for threads whose cancellation type is
PTHREADCANCELASYNCHRONOUS.
It is easier to arrange for deferred cancel safety, as this
requires system and program state protection only around
cancellation points. In general, expect that most applica-
tions and libraries are not Asynchronous-Cancel-Safe.
POSIX Threads Only
SunOS 5.11 Last change: 4 Oct 2005 5
Standards, Environments, and Macros cancellation(5)
The cancellation functions described in this manual page are
available for POSIX threads, only (the Solaris threads
interfaces do not provide cancellation functions).
EXAMPLES
Example 1 Cancellation example
The following short C] example shows the pushing/popping of
cancellation handlers, the disabling/enabling of cancella-
tion, the use of pthreadtestcancel(), and so on. The
freeres() cancellation handler in this example is a dummy
function that simply prints a message, but that would free
resources in a real application. The function f2() is called
from the main thread, and goes deep into its call stack by
calling itself recursively.
Before f2() starts running, the newly created thread has
probably posted a cancellation on the main thread since the
main thread calls thryield() right after creating thread2.
Because cancellation was initially disabled in the main
thread, through a call to pthreadsetcancelstate(), the call
to f2() from main() continues and constructs X at each
recursive call, even though the main thread has a pending
cancellation.
When f2() is called for the fifty-first time (when "i ==
50"), f2() enables cancellation by calling
pthreadsetcancelstate(). It then establishes a cancellation
point for itself by calling pthreadtestcancel(). (Because
a cancellation is pending, a call to a cancellation point
such as read(2) or write(2) would also cancel the caller
here.)
After the main() thread is canceled at the fifty-first
iteration, all the cleanup handlers that were pushed are
called in sequence; this is indicated by the calls to
freeres() and the calls to the destructor for X. At each
level, the C] runtime calls the destructor for X and then
the cancellation handler, freeres(). The print messages
from freeres() and X's destructor show the sequence of
calls.
SunOS 5.11 Last change: 4 Oct 2005 6
Standards, Environments, and Macros cancellation(5)
At the end, the main thread is joined by thread2. Because
the main thread was canceled, its return status from
pthreadjoin() is PTHREADCANCELED. After the status is
printed, thread2 returns, killing the process (since it is
the last thread in the process).
#include
#include
extern "C" void thryield(void);
extern "C" void printf(...);
struct X {
int x;
X(int i){x = i; printf("X(%d) constructed.\n", i);}
~X(){ printf("X(%d) destroyed.\n", x);}
};
void
freeres(void *i)
{
printf("Freeing `%d`\n",i);
}
char* f2(int i)
{
try {
X dummy(i);
pthreadcleanuppush(freeres, (void *)i);
if (i == 50) {
pthreadsetcancelstate(PTHREADCANCELENABLE, NUL);
pthreadtestcancel();
}
f2(i]1);
pthreadcleanuppop(0);
}
catch (int) {
printf("Error: In handler.\n");
}
return "f2";
}
void *
thread2(void *tid)
{
void *sts;
printf("I am new thread :%d\n", pthreadself());
pthreadcancel((pthreadt)tid);
SunOS 5.11 Last change: 4 Oct 2005 7
Standards, Environments, and Macros cancellation(5)
pthreadjoin((pthreadt)tid, &sts);
printf("main thread cancelled due to %d\n", sts);
return (sts);
}
main()
{
pthreadsetcancelstate(PTHREADCANCELDISABLE, NUL);
pthreadcreate(NUL, NUL, thread2, (void *)pthreadself());
thryield();
printf("Returned from %s\n",f2(0));
}
ATRIBUTES
See attributes(5) for descriptions of the following attri-
butes:
ATRIBUTE TYPE ATRIBUTE VALUE
MT-Level MT-Safe
SEE ALSO
read(2), sigwait(2), write(2), Intro(3), condition(5),
pthreadcleanuppop(3C), pthreadcleanuppush(3C),
pthreadexit(3C), pthreadjoin(3C),
pthreadsetcancelstate(3C), pthreadsetcanceltype(3C),
pthreadtestcancel(3C), setjmp(3C), attributes(5), stan-
dards(5)
SunOS 5.11 Last change: 4 Oct 2005 8
|