[英]Force blocking syscall of other thread to return and set errno to EINTR
請查看以下示例源代碼:
void tfunc()
{
// Some blocking syscall that sets errno
if (errno == EINTR)
{
std::cout << "cleanup" << std::endl;
return;
}
// Do some other stuff
}
int main(int argc, char *argv[])
{
std::thread t(tfunc);
sleep(10);
return 0;
}
是否有可能從另一個線程讓系統調用,例如accept()
返回並將errno
為EINTR
? 如果是,如何?
我建議你使用:
poll()
(或select()
或epoll()
) 在你生成你的線程之前,你設置一個 pipe 它將攜帶一個“中斷消息”。 在您的線程tfunc
中,您設置poll
以便它等待您要處理的文件描述符(套接字)和pipe 的讀取端。
如果要中斷,只需將“中斷消息”寫入 pipe 的寫入端; 並在poll
返回的線程中檢查 pipe 是否有數據要讀取。
小演示,沒有錯誤處理,沒有信號處理,只是為了形象化我的意思:
#include <cassert>
#include <iostream>
#include <thread>
#include <poll.h>
#include <unistd.h>
int fd[2];
void the_blocking_thread(void)
{
pollfd pollfds[2];
pollfds[0].fd = fd[0];
pollfds[0].events = POLLIN;
pollfds[1].fd = -99; // add here your socket / fd
pollfds[1].events = POLLIN; // or whatever you need
std::cout << "waiting for \"interrupt message\" or real work on fd" << std::endl;
int ret = poll(pollfds, 2, -1);
assert(ret > 0);
if (pollfds[0].revents != 0) {
std::cout << "cleanup" << std::endl;
return;
}
// Non blocking call on your fd
// Some other stuff
}
int main() {
int ret = pipe(fd);
assert(ret == 0);
std::cout << "Starting thread" << std::endl;
std::thread t(the_blocking_thread);
std::chrono::seconds timespan(1); // or whatever
std::this_thread::sleep_for(timespan);
std::cout << "Sending \"interrupt\" message" << std::endl;
char dummy = 42;
ret = write (fd[1], &dummy, 1);
assert(ret == 1);
t.join();
}
(直播)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.