简体   繁体   English

pthread_cancel()函数无法终止线程

[英]pthread_cancel() function failed to terminate a thread

I'm using pthread_create() and pthread_cancel() functions to create a multithreaded program, but I noticed that pthread_cancel() did not really terminate the thread it was supposed to. 我正在使用pthread_create()pthread_cancel()函数来创建多线程程序,但我注意到pthread_cancel()并没有真正终止它应该的线程。

void check(void *param){
    header_t *Bag = (header_t *) param;
    pthread_t timer_thread;
    while(true){
        if(Bag->size && TIMER_OFF){
            pthread_create(&timer_thread, NULL, (void *) &timer, (void *) Bag);
            printf("\nCREATE THREAD ID = %d\n", timer_thread);
            // ADD
        }
        else if(!TIMER_OFF && Bag->size >= 2 && Bag->next->time <= CURRENT_APT_TIME && CRRENT_TAG != Bag->next->tag){
            printf("\nOLD THREAD ID = %d TO BE CANCELLED\n", timer_thread);
            pthread_cancel(timer_thread);
            pthread_create(&timer_thread, NULL, (void *) &timer, (void *) Bag);
            printf("\nNEW THREAD ID = %d\n", timer_thread);
            // Replace
        }
        Sleep(1);
    }
}

timer function void timer(void *) is exactly what it sounds like, and I've included couple of lines to print out the thread ID of itself. 计时器功能void timer(void *)正是它听起来的样子,我已经包含几行来打印出自己的线程ID。

When tested, the following was seen: 测试时,发现以下情况:

...

OLD THREAD ID = 6041240 TO BE CANCELLED

NEW THREAD ID = 6046456

...

THREAD ID EXECUTING = 6041240

So the timer function was not terminated by calling pthread_cancel() ? 那么通过调用pthread_cancel()终止定时器功能?

By default your thread is created with the cancel type PTHREAD_CANCEL_DEFERRED , which means that you need to make sure that your thread has a so-called cancellation point . 默认情况下,您的线程是使用取消类型 PTHREAD_CANCEL_DEFERRED创建的,这意味着您需要确保您的线程具有所谓的取消点 That is, a point where cancel requests are checked and reacted upon. 也就是说,检查取消请求并作出反应的点。

This page contains a list of functions that are guaranteed to be cancellation points. 此页面包含一系列保证为取消点的功能。 Examples are some of the sleep() and pthread functions. 示例是一些sleep()和pthread函数。 You can also use pthread_testcancel() if you just need a function to purely test whether the thread has been canceled, and nothing else. 如果你只需要一个函数来纯粹测试线程是否被取消,你也可以使用pthread_testcancel()

Another option is to set your threads canceltype to be PTHREAD_CANCEL_ASYNCHRONOUS , by using pthread_setcanceltype() , which will make your thread cancelable even without cancellation points. 另一种选择是使用pthread_setcanceltype()将你的线程canceltype设置为PTHREAD_CANCEL_ASYNCHRONOUS ,即使没有取消点,你的线程也会被取消。 However, the system is still free to choose when the thread should actually be canceled, and you'll need to take great care to make sure that the system isn't left in an inconsistent state when cancelled (typically means avoiding any system calls and similar - see the list of Async-cancel-safe functions - it's short!). 但是,系统仍然可以自由选择何时实际取消线程,并且您需要非常小心地确保系统在取消时不会处于不一致状态(通常意味着避免任何系统调用和类似 - 请参阅Async-cancel-safe函数列表 - 它很简短!)。

In general, asynchronous cancellation should only be used for more or less "pure" processing threads, whereas threads performing system calls and similar are better implemented with deferred cancellation and careful placement of cancellation points. 通常,异步取消应该仅用于或多或少的“纯”处理线程,而执行系统调用的线程等通过延迟取消和仔细放置取消点来更好地实现。

Also, as long as you are not detaching your thread (by either creating it detached through its attribute, or by calling pthread_detach() after it is created), you will need to call pthread_join() on the timer thread to make sure that all resources are cleaned up after canceling it. 此外,只要你没有分离你的线程 (通过它的属性创建它分离,或者在创建它之后调用pthread_detach() ),你需要在定时器线程上调用pthread_join()以确保所有取消资源后清理资源。 Otherwise you might end up in a state without any spare threading resources, where you cannot create any new threads. 否则,您可能最终处于没有任何备用线程资源的状态,您无法创建任何新线程。

pthread_cancel()的默认取消方法是延迟取消。所以当你调用pthread_cancel() ,在指定的线程到达取消点之前它不会真正取消。你应该调用pthread_setcanceltype来为你的线程设置另一个取消方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM