Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
cancellation(5)						       cancellation(5)

NAME
       cancellation  -	overview of concepts related to	POSIX thread cancella-
       tion

       +-------------------------+-----------------------------------+
       |	FUNCTION	 |		ACTION		     |
       |pthread_cancel()	 | Cancels thread execution.	     |
       |pthread_setcancelstate() | Sets	the cancellation state of  a |
       |			 | thread.			     |
       |pthread_setcanceltype()	 | Sets	 the  cancellation type	of a |
       |			 | thread.			     |
       |pthread_testcancel()	 | Creates a cancellation  point  in |
       |			 | the calling thread.		     |
       |pthread_cleanup_push()	 | Pushes a cleanup handler routine. |
       |pthread_cleanup_pop()	 | Pops	a cleanup handler routine.   |
       +-------------------------+-----------------------------------+

   Cancellation
       Thread  cancellation allows a thread to terminate the execution 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 cancellation is
       an asynchronously-generated cancel condition such as a user  requesting
       to close	or exit	some running operation.	Another	example	is the comple-
       tion 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 pthread_can-
	   cel(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	 pthread_cleanup_push(3C).  Wherever  a	 thread	 restores  the
	   changed state, pop the cleanup handler from the cleanup stack  with
	   pthread_cleanup_pop(3C).

       4.  Know	 whether the threads you are canceling call into cancel-unsafe
	   libraries, and disable cancellation with pthread_setcancelstate(3C)
	   before  the call into the library.  See Cancellation	State and Can-
	   cel-Safe.

       5.  To cancel a thread in a procedure  that  contains  no  cancellation
	   points,  insert  your own cancellation points with pthread_testcan-
	   cel(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 (can-
       cellation points), and you can create additional	cancellation points in
       your application	with pthread_testcancel().

       The  following  cancellation points are	defined	by the system (system-
       defined cancellation  points):  aio_suspend(3RT),  close(2),  creat(2),
       getmsg(2),  getpmsg(2),	lockf(3C),  mq_receive(3RT), mq_send(3RT), ms-
       grcv(2),	 msgsnd(2),  msync(3C),	 nanosleep(3RT),  open(2),   pause(2),
       poll(2),	 pread(2),  pthread_cond_timedwait(3C),	pthread_cond_wait(3C),
       pthread_join(3C),   pthread_testcancel(3C),   putmsg(2),	   putpmsg(2),
       pwrite(2),  read(2), readv(2), select(3C), sem_wait(3RT), sigpause(3C),
       sigwaitinfo(3RT),   sigsuspend(2),    sigtimedwait(3RT),	   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 F_SETLKW	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 cancellation is deferred (the	default	case),
       cancellation occurs only	within the scope of a function	defined	 as  a
       cancellation  point  (after the function	is called and before the func-
       tion returns). See Cancellation Type for	 more  information  about  de-
       ferred and asynchronous cancellation.

       Choosing	 where to place	cancellation points and	understanding how can-
       cellation 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 cancel-
       lation point.  Operations need to check for  pending  cancellation  re-
       quests when the operation is about to block indefinitely. This includes
       threads waiting in  pthread_cond_wait()	and  pthread_cond_timedwait(),
       threads	 waiting   for	 the   termination   of	  another   thread  in
       pthread_join(), 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 care-
       lessly  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 pthread_cleanup_push(3C) before the
       cancellation 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 re-
       turns, the thread-specific data destructor functions are	called.	Thread
       execution terminates when the last destructor function returns.

       When,  in  the  normal  course of the program, an uncanceled thread re-
       stores state that it had	previously changed, be sure to pop the cleanup
       handler	(that  you  had	 set  up  where	 the  change took place) using
       pthread_cleanup_pop(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.

       The pthread_cleanup_push() and pthread_cleanup_pop() functions  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
       pthread_cleanup_push()  macro  can be thought to	expand to a token list
       whose first token is '{'	with pthread_cleanup_pop() expanding to	a  to-
       ken list	whose last token is the	corresponding '}').

       The  effect  of	the use	of return, break, continue, and	goto to	prema-
       turely leave a code block described by a	pair of	pthread_cleanup_push()
       and pthread_cleanup_pop() function calls	is undefined.

   Cancellation	State
       Most  programmers  will	use  only  the	default	 cancellation state of
       PTHREAD_CANCEL_ENABLE, but can choose to	 change	 the  state  by	 using
       pthread_setcancelstate(3C), which determines whether a thread is	cance-
       lable at	all. With the default state of	PTHREAD_CANCEL_ENABLE, cancel-
       lation  is enabled and the thread is cancelable at points determined by
       its cancellation	type. See Cancellation Type.

       If the state is PTHREAD_CANCEL_DISABLE, cancellation is	disabled,  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	pthread_setcanceltype(3C), and
       determines whether the thread can be canceled anywhere in its execution
       or only at cancellation points.

       With the	default	type of	 PTHREAD_CANCEL_DEFERRED, the thread is	cance-
       lable  only  at cancellation points, and	then only when cancellation is
       enabled.

       If the type is PTHREAD_CANCEL_ASYNCHRONOUS, 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  se-
       quences with no external	dependencies that could	result in dangling re-
       sources or unresolved state conditions. Using asynchronous cancellation
       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   oc-	 | All	 cancellation |
       |		    |curs when the tar-	 | requests   to  the |
       |		    |get thread	reaches	 | target thread  are |
       |		    |a	   cancellation	 | held	pending.      |
       |		    |point and a cancel	 |		      |
       |		    |is	 pending.  (De-	 |		      |
       |		    |fault)		 |		      |
       |Asynchronous	    |Receipt	of    a	 | All	 cancellation |
       |		    |pthread_cancel()	 | requests  to	  the |
       |		    |call  causes imme-	 | target  thread are |
       |		    |diate    cancella-	 | held	 pending;  as |
       |		    |tion.		 | soon	 as cancella- |
       |		    |			 | tion	  is   re-en- |
       |		    |			 | abled,     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 applica-
       tion 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
       PTHREAD_CANCEL_DEFERRED.	See Cancellation  State.  It  is  specifically
       Asynchronous-Cancel-Safe	 when it is Cancel-Safe	for threads whose can-
       cellation type is PTHREAD_CANCEL_ASYNCHRONOUS.

       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 applications and libraries are	not  Asynchro-
       nous-Cancel-Safe.

   POSIX Threads Only
       The  cancellation functions described in	this manual page are available
       for POSIX threads, only (the Solaris threads interfaces do not  provide
       cancellation functions).

       Example 1: Cancellation example

       The  following short C++	example	shows the pushing/popping of cancella-
       tion handlers, the  disabling/enabling  of  cancellation,  the  use  of
       pthread_testcancel(), and so on.	The free_res() 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  it-
       self recursively.

       Before  f2()  starts  running,  the  newly  created thread has probably
       posted a	cancellation on	the main thread	since the  main	 thread	 calls
       thr_yield()  right  after  creating  thread2.  Because cancellation was
       initially disabled in the main thread, through a	call  to  pthread_set-
       cancelstate(), the call to f2() from  main() continues and constructs X
       at each recursive call,	even though the	main thread has	a pending can-
       cellation.

       When  f2()  is  called for the fifty-first time (when "i	== 50"),  f2()
       enables cancellation by calling pthread_setcancelstate(). It  then  es-
       tablishes  a cancellation point for itself by calling  pthread_testcan-
       cel(). (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  free_res() and the calls to	the destructor
       for X. At each level, the C++ runtime calls the destructor  for	X  and
       then  the  cancellation	handler,   free_res(). The print messages from
       free_res() and X's destructor show the sequence of calls.

       At the end, the main thread is joined  by  thread2.  Because  the  main
       thread	was  canceled,	its  return  status  from   pthread_join()  is
       PTHREAD_CANCELED. After the status is printed, thread2 returns, killing
       the  process (since it is the last thread in the	process).

       #include	<pthread.h>
       #include	<sched.h>
       extern "C" void thr_yield(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
       free_res(void *i)
       {
	       printf("Freeing `%d`\n",i);
       }

       char* f2(int i)
       {
	       try {
	       X dummy(i);
	       pthread_cleanup_push(free_res, (void *)i);
	       if (i ==	50) {
		      pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
		   pthread_testcancel();
	       }
	       f2(i+1);
	       pthread_cleanup_pop(0);
	       }
	       catch (int) {
	       printf("Error: In handler.\n");
	       }
	       return "f2";
       }

       void *
       thread2(void *tid)
       {
	       void *sts;

	       printf("I am new	thread :%d\n", pthread_self());

	       pthread_cancel((pthread_t)tid);

	       pthread_join((pthread_t)tid, &sts);

	       printf("main thread cancelled due to %d\n", sts);

	       return (sts);
       }

       main()
       {
	       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
	       pthread_create(NULL, NULL, thread2, (void *)pthread_self());
	       thr_yield();
	       printf("Returned	from %s\n",f2(0));
       }

       See attributes(5) for descriptions of the following attributes:

       +-----------------------------+-----------------------------+
       |      ATTRIBUTE	TYPE	     |	    ATTRIBUTE VALUE	   |
       +-----------------------------+-----------------------------+
       |MT-Level		     |MT-Safe			   |
       +-----------------------------+-----------------------------+

       read(2),	     sigwait(2),     write(2),	   intro(3),	 condition(5),
       pthread_cleanup_pop(3C),	 pthread_cleanup_push(3C),   pthread_exit(3C),
       pthread_join(3C),     pthread_setcancelstate(3C),    pthread_setcancel-
       type(3C),  pthread_testcancel(3C),  setjmp(3C),	attributes(5),	 stan-
       dards(5)

				  4 Oct	2005		       cancellation(5)

NAME

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=cancellation&sektion=5&manpath=SunOS+5.10>

home | help