简体   繁体   English

强制阻止其他线程的系统调用返回并将 errno 设置为 EINTR

[英]Force blocking syscall of other thread to return and set errno to EINTR

please view the following example source code:请查看以下示例源代码:

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;
}

Is it possible, from another thread, to have the syscall, for example accept() return and set errno to EINTR ?是否有可能从另一个线程让系统调用,例如accept()返回并将errnoEINTR If yes, how?如果是,如何?

I suggest you use:我建议你使用:

  • non-blocking operations非阻塞操作
  • poll() (or select() or epoll() ) poll() (或select()epoll()
  • a pipe一个 pipe

Before you spawn your thread you setup a pipe which will carry an "interrupt message".在你生成你的线程之前,你设置一个 pipe 它将携带一个“中断消息”。 In your thread tfunc you setup poll such that it waits on both the file descriptor (socket) you want to work on and the read end of the pipe.在您的线程tfunc中,您设置poll以便它等待您要处理的文件描述符(套接字)pipe 的读取端。

If you want to interrupt that you simply write an "interrupt message" to the write end of the pipe;如果要中断,只需将“中断消息”写入 pipe 的写入端; and in the thread check on return of poll whether the pipe has data to read.并在poll返回的线程中检查 pipe 是否有数据要读取。

Small demo, no error handling, no handling of signals, just to visualize what I mean:小演示,没有错误处理,没有信号处理,只是为了形象化我的意思:

#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();
}

( Live ) 直播

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

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