简体   繁体   中英

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 ? If yes, how?

I suggest you use:

  • non-blocking operations
  • poll() (or select() or epoll() )
  • a pipe

Before you spawn your thread you setup a pipe which will carry an "interrupt message". 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.

If you want to interrupt that you simply write an "interrupt message" to the write end of the pipe; and in the thread check on return of poll whether the pipe has data to read.

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 )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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