线程取消的语义是向目标线程发Cancel信号,但如何处理Cancel信号则由目标线程自己决定,或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点),由不同的Cancelation状态决定。根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。
intpthread_setcanceltype(int
type, int *oldtype)
设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYNCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
#include
#include
#include
void* threadFunc(void*
args)
{
pthread_setcanceltype(PTHREAD_CANCEL_ASYCHRONOUS);
while (1);
return NULL;
}
int main(void)
{
pthread_t tid;
pthread_setcancelstate();
if (pthread_create(&tid, NULL,
threadFunc, NULL))
{
printf("Error Creating
Thread.\n");
return 1;
}
sleep(3);
pthread_cancel(tid);
pthread_join(tid, NULL);
return 0;
}
pthread_cancel 与exception貌似毫无关联,实际上,In NPTL thread cancellation is implemented using
exceptions. This does not in general conflict with the mixed use of
cancellation and exceptions in C++ programs.The problem is in
functiontf.
This function contains a catch-all clause which does not rethrow
the exception. This is possible to expect but should really never
happen in any code. The rules C++ experts developed state that
catch-all cases must rethrow. If not then strange things can happen
since one doesn't always know exactly what exceptions are
thrown.The exception used for cancellation is special, it
cannot be ignored.
#include
#include
#include
static pthread_mutex_t m =
PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t c =
PTHREAD_COND_INITIALIZER;
static void*
tf(void*)
{
try
{
::pthread_mutex_lock(&m);
::pthread_cond_wait(&c, &m);
}
catch (...)
{
// do something
}
}
int main()
{
pthread_t th;
::pthread_create(&th, NULL, tf, NULL);
std::cout << "Wait a bit"
<< std::endl;
sleep(1);
::pthread_cancel(th);
::pthread_join(th, NULL);
}
But this code might not have the expected
semantics. Therefore the more general solution is to change the
code as such:
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
static pthread_mutex_t m =
PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t c =
PTHREAD_COND_INITIALIZER;
@@ -11,6 +12,8 @@
try {
::pthread_mutex_lock(&m);
::pthread_cond_wait (&c, &m);
+ } catch (abi::__forced_unwind&) {
+ throw;
}
catch (...) {
// do something
}