【问题标题】:Kill a blocking thread in C's pthread gracefully?优雅地杀死 C 的 pthread 中的阻塞线程?
【发布时间】:2011-06-14 10:33:27
【问题描述】:

假设我有一个类似这样的线程:

void my_thread(char *device_name) {
    int fd = open(device_name, O_RDONLY);
    struct input_event ev;

    while(1) {
        read(fd, &ev, sizeof(struct input_event));
        /* do something */
    }
}

如何停止这样的线程?一种方法是使用pthread_cancel,但我宁愿做得更优雅。可能是pthread_kill 之类的东西?但是,在这种情况下,read 方法是否会解除阻塞(我认为应该如此),线程将如何处理信号?还是应该处理它的进程?

非常感谢您的建议!

【问题讨论】:

  • 您能否设计您的应用程序,以便无需杀死这些类型的线程?这避免了杀死它的问题。在应用程序退出并且操作系统销毁所有线程之前,您能不能只留下这个线程?如果设备死机,那么您无能为力:(

标签: c multithreading pthreads blocking


【解决方案1】:

对此的答案是不要做任何会在没有超时的情况下阻塞的事情。对于 IO,您不应该调用 read(),直到您知道调用不会阻塞。例如,首先在路径上使用 poll() 或 select() 以确定状态。

【讨论】:

  • 不过,这并不能真正回答问题。如果您有一个超时时间很长的阻塞调用怎么办?
  • 是的,但是……不要。避免像瘟疫一样阻塞电话。使用阻塞呼叫进行编码就像使用打孔卡一样。它是面向批处理的。
  • @Oli -- 它确实回答了这个问题:不要这样做。如果你在内核中阻塞,你不能终止你的线程,除非通过你被阻塞的任何内核代码的优雅。发送信号可能会解除阻塞,也可能不会,它可能取决于哪个信号(并且 SIGKILL 不能保证当你在内核代码中时要特别)。因此,套用电影战争游戏的话说,获胜的唯一方法就是不玩。
  • @mah:也许我错过了什么!假设我们有一个工作线程来处理,例如网络 I/O。您如何建议在没有某种阻塞机制的情况下让该线程空闲等待输入? (AFAIK,select 也会在超时期间阻塞,或者直到输入准备好。)
  • @mah: 如果一段时间没有收到数据,setsockopt(SO_RCVTIMEO) 会使 recv() 返回。就像 select() 但没有 select()。
【解决方案2】:

您的问题实际上是“如何中断来自其他线程的阻塞系统调用”。

尝试搜索它。这是类似的讨论之一:Proper way to close a blocking UDP socket

【讨论】:

  • 从另一个线程关闭套接字句柄在 Windows 上工作正常 - 取消阻塞调用。在 Linux 上关闭另一个线程的套接字句柄可以正常工作 - 取消阻塞调用。在 UDP 套接字上的阻塞调用的特殊情况下(如链接中所示),向本地端口发送 UDP 消息以说服调用返回有什么问题?然后线程可以意识到它必须死亡并自行终止。
  • 如果您不介意以下操作,可以使用 UDP 完成: a) 保持 UDP 套接字未绑定,否则您无法发送给它; b) 在关机期间创建新的套接字; c)丢失与您的“解锁”数据包完全相同的真实数据包:没有保证区分“读取”和“假”数据包的方法。至于“工作正常”——当 FreeBSD 升级破坏了我的应用程序时,这对我来说是一个非常令人讨厌的惊喜,因为 close() 之前工作正常,之后永远卡住了。
【解决方案3】:

你不能优雅地终止线程。如果要干净退出,请确保线程根据某些条件退出。

【讨论】:

  • 在您的情况下添加 while(bExitThread),其中 bExitThread 是可变变量,可以从另一个线程更改。
  • 这很明显。我对阻塞 read 功能感到困扰。
  • 如果他在一个 read() 调用中被阻塞,并且很长一段时间都不会解除阻塞(如果有的话),他将很难读取那个条件变量。你说的是正确的,但次要于首先不失控地阻塞。
  • 尝试使用 IO 完成端口或类似的东西?如果线程会在合理的时间内退出,只是泄漏线程?如果没有更多关于架构的信息,很难说。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多