How to wake select () during a timeout from another thread

According to the information "a person chooses":

"On success, select() and pselect() return the number of file descripโ€ tors contained in the three returned descriptor sets which may be zero if the timeout expires before anything interesting happens. On error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined, so do not rely on their contents after an error." 

Choose wakup because of:

  1)read/write availability 2)select error 3)descriptoris closed. 

However, how can we wake select () from another thread if there is no data available and the choice is still in timeout?

[update]
Pseudo code

  // Thread blocks on Select void *SocketReadThread(void *param){ ... while(!(ReadThread*)param->ExitThread()) { struct timeval timeout; timeout.tv_sec = 60; //one minute timeout.tv_usec = 0; fd_set rds; FD_ZERO(&rds); FD_SET(sockfd, &rds)' //actually, the first parameter of select() is //ignored on windows, though on linux this parameter //should be (maximum socket value + 1) int ret = select(sockfd + 1, &rds, NULL, NULL, &timeout ); //handle the result //might break from here } return NULL; } //main Thread int main(){ //create the SocketReadThread ReaderThread* rthread = new ReaderThread; pthread_create(&pthreadid, NULL, SocketReaderThread, NULL, (void*)rthread); // do lots of things here ............................ //now main thread wants to exit SocketReaderThread //it sets the internal state of ReadThread as true rthread->SetExitFlag(true); //but how to wake up select ?????????????????? //if SocketReaderThread currently blocks on select } 

[UPDATE]
1) @trojanfoe provides a method to achieve this; its method writes socket data (possibly dirty data or message exit data) to select wakeup. I am going to pass the test and update the result.
2) Another thing worth mentioning is that closing a socket does not guarantee waking up a function call, see this post .

[UPDATE2]
After many tests, here are some facts about waking select:
1) If the socket viewed by select is closed by another application , then select () the call will wake up immediately. Further reading or writing to the socket will receive a return value of 0 with errno = 0
2) If the socket viewed by select is closed by another thread of the same application , then select () will not wake up before the timeout if there is no data to read or write. After selecting timeouts, performing a read / write operation results in an error with errno = EBADF (since the socket was closed by another thread during the wait period)

+4
source share
1 answer

I use an event object based on pipe() :

IoEvent.h:

 #pragma once class IoEvent { protected: int m_pipe[2]; bool m_ownsFDs; public: IoEvent(); // Creates a user event IoEvent(int fd); // Create a file event IoEvent(const IoEvent &other); virtual ~IoEvent(); /** * Set the event to signalled state. */ void set(); /** * Reset the event from signalled state. */ void reset(); inline int fd() const { return m_pipe[0]; } }; 

IoEvent.cpp:

 #include "IoEvent.h" #include <string.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <poll.h> using namespace std; IoEvent::IoEvent() : m_ownsFDs(true) { if (pipe(m_pipe) < 0) throw MyException("Failed to create pipe: %s (%d)", strerror(errno), errno); if (fcntl(m_pipe[0], F_SETFL, O_NONBLOCK) < 0) throw MyException("Failed to set pipe non-blocking mode: %s (%d)", strerror(errno), errno); } IoEvent::IoEvent(int fd) : m_ownsFDs(false) { m_pipe[0] = fd; m_pipe[1] = -1; } IoEvent::IoEvent(const IoEvent &other) { m_pipe[0] = other.m_pipe[0]; m_pipe[1] = other.m_pipe[1]; m_ownsFDs = false; } IoEvent::~IoEvent() { if (m_pipe[0] >= 0) { if (m_ownsFDs) close(m_pipe[0]); m_pipe[0] = -1; } if (m_pipe[1] >= 0) { if (m_ownsFDs) close(m_pipe[1]); m_pipe[1] = -1; } } void IoEvent::set() { if (m_ownsFDs) write(m_pipe[1], "x", 1); } void IoEvent::reset() { if (m_ownsFDs) { uint8_t buf; while (read(m_pipe[0], &buf, 1) == 1) ; } } 

You can cut member m_ownsFDs ; I'm not even sure that I use this anymore.

+6
source

Source: https://habr.com/ru/post/1489275/


All Articles