我有一个线程,它在这样的循环中从原始HCI套接字读取消息:
void* loop_hci (void* args) {
params_hci_t* params = (params_hci_t*) args;
int result_hci = 0;
uint8_t* buf_hci = calloc(1, HCI_EVENT_MAX_LENGTH);
while (!poll_end()) {
result_hci = read(params->hci_sock, buf_hci, HCI_EVENT_MAX_LENGTH);
if (result_hci > 0) {
// ... do stuff with the received data
}
}
ancs_pdebug("HCI loop shutting down...");
return NULL;
}
poll_end()
功能运行良好,符合预期。它返回0,直到收到SIGINT信号,然后返回1。
在主线程中,我创建了这样的套接字:
hci_sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
还有线程:
ph->hci_sock = hci_sock;
pthread_create(&t_hci, NULL, &loop_hci, ph);
然后在一段时间后像这样调用关闭(在主线程中):
shutdown(hci_sock, SHUT_RD);
我假设read()应该在我调用shutdown()后返回,我在不同的线程中为L2CAP套接字使用相同的方法,它工作得很好。但事实并非如此。我在主线程中的pthread_join(t_hci, NULL)
调用永远不会返回。
插座工作正常。我可以从中读取消息。我也试着调用close(线程结束后我会这样做),但结果是一样的。
可能是什么问题,或者我的假设是错误的?
您遇到的问题可能是因为处理套接字和多线程的方式。您不应该将shutdown与原始套接字一起使用。它是为连接的套接字设计的,我真的从来没有用过原始套接字或数据包套接字。但有一个建议是杀死或取消一个线程,我会避免,因为杀死一个线程是暴力行为,而且你有不按顺序处理资源的风险。相反,您应该以不同的方式设计解决方案:
-
一种可能性是将非阻塞套接字与select、poll或epoll一起使用。您将有一个循环,在select/poll/epoll中等待,直到套接字准备好或超时。当您想要关闭套接字时,只需将一个变量(例如endLoop)设置为true,指示轮询线程应该离开循环。请参阅男子选择:http://man7.org/linux/man-pages/man2/select.2.html
-
例如,Thrift服务器中使用的另一种可能性是让应用程序向自己发送一条带有特定代码的特殊消息。侦听线程取消阻止并读取此特殊消息,该消息指示它应该检查是否必须完成侦听(例如,通过读取变量值)。
因此,当侦听线程正在侦听或读取时,主线程将变量endLoop变量设置为true,指示它完成,或者它将执行(2)来取消阻止侦听线程。
这两个选项是处理问题的好方法。使用非阻塞套接字(1),或者通过向其自身发送消息来解除阻塞读取或侦听线程。