Linux 如何终止 pthread 中的休眠线程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4778361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to terminate a sleeping thread in pthread?
提问by qiuxiafei
I have thread which sleeps for a long time, then wakes up to do something, then sleep again, like this:
我有一个线程睡了很长时间,然后醒来做某事,然后再次睡觉,就像这样:
while(some_condition)
{
// do something
sleep(1000);
}
How could I make this thread exit gracefully and QUICKLY?
我怎样才能让这个线程优雅而快速地退出?
I tried to use pthread_cancel()
, but sleeping threads could not be canceled.
I also tried changing the condition of the while loop, but it will still take long to exit.
And I don't want to use pthread_kill()
, since it may kill the thread when it's working.
我尝试使用pthread_cancel()
,但无法取消休眠线程。我也尝试过更改 while 循环的条件,但退出仍然需要很长时间。而且我不想使用pthread_kill()
,因为它可能会在线程工作时杀死它。
So, are there any good ideas?
那么,有什么好的想法吗?
采纳答案by karoberts
As an alternative to sleep
, you could use pthread_cond_timedwaitwith a 1000 ms timeout. Then when you want to exit, signal the condition variable.
作为 的替代方法sleep
,您可以使用pthread_cond_timedwait和 1000 毫秒超时。然后当你想退出时,给条件变量发信号。
This is similar to how you might do this in C#/Java using wait and notify.
这类似于在 C#/Java 中使用等待和通知执行此操作的方式。
回答by ephemient
The classic UNIX condition variable is the self-pipe.
经典的 UNIX 条件变量是self-pipe。
int fds[2];
pipe2(fds, O_NONBLOCK); // requires newish kernel and glibc; use pipe + 2*fcntl otherwise
child:
while (some_condition) {
// do something
struct pollfd pd = { .fd = fds[0], .events = POLLIN };
int rc;
char c;
while ((rc = poll(&pd, 1, 1000000)) == -1 && errno == EINTR)
// not entirely correct; 1000000 should be decreased according to elapsed time when repeating after a signal interruption
;
if (rc > 0 && (pd.revents & POLLIN) && read(fds[0], &c, 1) >= 0)
break;
}
parent:
cancel() {
char c = 0;
write(fds[1], &c, 1);
}
Yeah, it's a lot of fiddly (and untested) code. You should probably just use pthread_cond_wait
, it requires a pthread_mutex_t
and a pthread_cond_t
but is much easier.
是的,它有很多繁琐(且未经测试)的代码。您可能应该只使用pthread_cond_wait
,它需要 apthread_mutex_t
和 apthread_cond_t
但要容易得多。
回答by johnnycrash
Did you use pthread_cleanup_push and pop? Canceling with pthread_cancel doesn't work without them. You must use them in pairs just like I did in the example below. if you forget one it wont compile (fancy macros, one has the '{' and the other has the '}'). You can even nest different levels of cleanup/pops. Anyway, they set a long jump point that cancel jumps to when cancel occurs (pretty cool). Also, if your test program does not wait for the thread to start or to stop, you may not notice the canceling happening.
你用过 pthread_cleanup_push 和 pop 吗?没有它们,使用 pthread_cancel 取消将不起作用。您必须成对使用它们,就像我在下面的示例中所做的那样。如果你忘记了一个它不会编译(花哨的宏,一个有'{',另一个有'}')。您甚至可以嵌套不同级别的清理/弹出。无论如何,他们设置了一个远跳点,当取消发生时取消跳转(非常酷)。此外,如果您的测试程序不等待线程启动或停止,您可能不会注意到取消的发生。
Example:
例子:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static void *ThreadProc(void * arg);
static void unwind(__attribute__ ((unused)) void *arg);
int _fActive = 0;
int main(int argc, char** argv)
{
pthread_t Thread;
int nRet;
nRet = pthread_create(&Thread, NULL, ThreadProc, NULL);
printf("MAIN: waiting for thread to startup...\n");
while (_fActive == 0)
nanosleep(&(struct timespec){ 0, 0}, NULL);
printf("MAIN: sending cancel...\n");
nRet = pthread_cancel(Thread);
printf("MAIN: waiting for thread to exit...\n");
while (_fActive)
nanosleep(&(struct timespec){ 0, 0}, NULL);
printf("MAIN: done\n");
return 0;
}
static void unwind(__attribute__ ((unused)) void *arg)
{
// do some cleanup if u want
printf("THREAD: unwind (all threads, canceled or normal exit get here)\n");
_fActive = 0;
}
static void *ThreadProc(void * arg)
{
pthread_cleanup_push(unwind, arg);
// optional : pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
printf("THREAD: Enter Sleep\n");
_fActive = 1;
sleep(1000000);
printf("THREAD: Exit Sleep (canceled thread never gets here)\n");
pthread_cleanup_pop(1);
printf("THREAD: Exit (canceled thread never gets here)\n");
return NULL;
}
Program output:
程序输出:
MAIN: waiting for thread to startup...
THREAD: Enter Sleep
MAIN: sending cancel...
MAIN: waiting for thread to exit...
THREAD: unwind (all threads, canceled or normal exit get here)
MAIN: done
Notice how the cancel blows out of ThreadProc at the cancel point sleep() and executes only the unwind() function.
注意取消如何在取消点 sleep() 处从 ThreadProc 中删除并仅执行 unwind() 函数。