linux c实现线程超时退出,c – 如何在另一个线程的超时内唤醒select()
根據(jù)“男人選擇”信息:
"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."
選擇將wakup因?yàn)?#xff1a;
1)read/write availability
2)select error
3)descriptoris closed.
但是,如果沒有可用數(shù)據(jù)并且select仍在超時范圍內(nèi),我們?nèi)绾螐牧硪粋€線程喚醒select()?
[更新]
偽代碼
// 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提供了一種實(shí)現(xiàn)此目的的方法,他的方法將套接字?jǐn)?shù)據(jù)(可能是臟數(shù)據(jù)或退出消息數(shù)據(jù))寫入喚醒選擇.我將進(jìn)行測試并在那里更新結(jié)果.
2)另外要提一下,關(guān)閉套接字并不能保證喚醒select函數(shù)調(diào)用,請參見this post.
[UPDATE2]
做了很多測試后,這里有一些關(guān)于喚醒選擇的事實(shí):
1)如果select監(jiān)視的套接字被另一個應(yīng)用程序關(guān)閉,則select()調(diào)用
會立刻醒來.此后,讀取或?qū)懭胩捉幼謱⑹褂胑rrno = 0獲得返回值0
2)如果select監(jiān)視的套接字被同一應(yīng)用程序的另一個線程關(guān)閉,
如果沒有要讀取或?qū)懭氲臄?shù)據(jù),則select()將在超時之前不會喚醒.選擇超時后,使用errno = EBADF進(jìn)行讀/寫操作會導(dǎo)致錯誤
(因?yàn)樘捉幼衷诔瑫r期間已被另一個線程關(guān)閉)
解決方法:
我使用基于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
#include
#include
#include
#include
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)
;
}
}
你可以拋棄m_ownsFDs成員;我甚至不確定我是否會再使用它了.
標(biāo)簽:c-2,linux,tcp,multithreading,sockets
來源: https://codeday.me/bug/20190529/1177712.html
總結(jié)
以上是生活随笔為你收集整理的linux c实现线程超时退出,c – 如何在另一个线程的超时内唤醒select()的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++的一些关键字
- 下一篇: linux 系统 可视化工具实时监控_L