根据“男人选择”信息:

"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因为:

1)read/write availability

2)select error

3)descriptoris closed.

但是,如果没有可用数据并且select仍在超时范围内,我们如何从另一个线程唤醒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提供了一种实现此目的的方法,他的方法将套接字数据(可能是脏数据或退出消息数据)写入唤醒选择.我将进行测试并在那里更新结果.

2)另外要提一下,关闭套接字并不能保证唤醒select函数调用,请参见this post.

[UPDATE2]

做了很多测试后,这里有一些关于唤醒选择的事实:

1)如果select监视的套接字被另一个应用程序关闭,则select()调用

会立刻醒来.此后,读取或写入套接字将使用errno = 0获得返回值0

2)如果select监视的套接字被同一应用程序的另一个线程关闭,

如果没有要读取或写入的数据,则select()将在超时之前不会唤醒.选择超时后,使用errno = EBADF进行读/写操作会导致错误

(因为套接字在超时期间已被另一个线程关闭)

解决方法:

我使用基于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成员;我甚至不确定我是否会再使用它了.

标签:c-2,linux,tcp,multithreading,sockets

来源: https://codeday.me/bug/20190529/1177712.html

linux c实现线程超时退出,c – 如何在另一个线程的超时内唤醒select()相关推荐

  1. 用三个线程实现生产者消费者模型,其中一个线程作为生产者,二个线程作为消费者,生产者随机生产一个时间戳或者字符串,消费者消费这个时间戳,并不能重复消费,并将其打印出来

    题目要求: 用三个线程实现生产者消费者模型,其中一个线程作为生产者,二个线程作为消费者,生产者随机生产一个时间戳或者字符串,消费者消费这个时间戳,并不能重复消费,并将其打印出来.(这是一道百度面试的算 ...

  2. 工作中如何使用线程池的?自己如何定义一个线程池?

    工作中如何使用线程池的?自己如何定义一个线程池? import java.util.concurrent.*;public class MyThreadPoolDemo {public static ...

  3. 关于PrintQueueCollection()类,跨线程调用错误“线程无法访问此对象,因为另一个线程拥有该对象”

    使用System.Printing.PrintQueueCollection()   纸质打印机获取 _generalPrinters = new PrintQueueCollection(); pu ...

  4. java编写两个线程,一个线程打印1-52的整数,另一个线程打印字母A-Z。打印顺序为12A34B56C….5152Z。即按照整数和字母的顺序从小到大打印,并且每打印两个整数后,打印一个字母,交替

    2.编写两个线程,一个线程打印1-52的整数,另一个线程打印字母A-Z.打印顺序为12A34B56C-.5152Z.即按照整数和字母的顺序从小到大打印,并且每打印两个整数后,打印一个字母,交替循环打印 ...

  5. 设计两个个线程模拟存取款操作,其中一个线程每次随机存1~1000元钱,另外一个线程取1-1000元钱,如果余额不足,则取款失败,提示余额不足。写出程序(考虑并发问题)。

    设计两个个线程模拟存取款操作,其中一个线程每次随机存1~1000元钱, 另外一个线程取1-1000元钱,如果余额不足,则取款失败,提示余额不足. 写出程序(考虑并发问题). import java.u ...

  6. java 用户线程如何修改界面内容_java 加入一个线程、创建有响应的用户界面 。 示例代码...

    javajava 加入一个线程.创建有响应的用户界面 . 示例代码 来自thinking in java 4 21章 部分代码 目录21.2.11 package org.rui.thread.con ...

  7. python线程暂停_在python中暂停一个线程和另一个线程

    我正在研究如何在python中执行多线程(2个线程).在 我要他们中的一个一直在读串行端口.读取每个帧并将其保存到数据库中.我已经做了一个脚本来做这个.在 对于第二个,我希望它监听一个套接字端口.当它 ...

  8. python 线程重启_在Python中重新启动一个线程

    我正在尝试为 Python 3.4中的项目制作线程飞行软件,其中我需要线程重新启动,以防在传感器读取期间发生I / O错误或其他类似的侥幸崩溃.因此,我正在制作一个看门狗来检查线程是否已经死亡并重新启 ...

  9. 线程退出【Linux学习】pthread_create主线程与创建的新线程之间退出关系

    本篇文章个人在青岛吃饭的时候突然想到的...最近就有想写几篇关于线程退出的文章,所以回家到之后就奋笔疾书的写出来发布了 我们在一个线程中经常会创立另外的新线程,如果主线程退出,会不会影响它所创立的新线 ...

最新文章

  1. Linux Mint 19 安装Gnome Boxes 新建失败
  2. 新手必看,17 个常见的 Python 运行时错误
  3. php接口性能测试工具,PHP 应用性能优化指南
  4. 深入理解C程序内存布局
  5. linux glibc 编译安装,glibc的安装编译
  6. 向seaborn传递matplotlib绘图参数,精细地控制seaborn输出图形
  7. 办公技巧:Excel日常高频使用技巧,赶快收藏吧!
  8. Chrome 调试技巧 1
  9. 牛客题霸 [字符串的排列] C++题解/答案
  10. 【目标检测】NMS和soft-NMS详解及代码实现
  11. C语言基础之--sizeof()运算符的使用以及注意
  12. SpringMvc-HandlerMapping/RequestCondition
  13. 欧姆龙cp1h指令讲解_欧姆龙PLC编程指令含义及其用法
  14. 计算机中算术逻辑单元负责,算术逻辑单元可实现 算术逻辑单元的发展
  15. 如何删除双系统中的其中一个(完全删除)
  16. Nginx-负载均衡部署
  17. C#替换方向性的 Unicode 控制字符,解决无法匹配iphone 通讯录复制的手机号码问题
  18. 【英语学习】关于音标的汇总图分享
  19. centos 6.9界面中文显示英文或者英文界面改中文
  20. Java线程同步容易犯错的坑

热门文章

  1. java 通过反射得到命名空间_利用反射得到一个命名空间下的所有类,并调用?...
  2. dsniff 和 Ettercap 和 bettercap 详解 - 网络嗅探工具包
  3. Effective Java~57. 将局部变量的作用域最小化
  4. oracle表参数,Oracle 表的创建 及相关参数
  5. php保存rar,php 解压rar文件
  6. oracle 会话 临时表,Oracle 学习系列之二(会话与事务级临时表)
  7. 砥志研思SVM(三) 最优间隔分类器问题(下):软间隔SVM
  8. 逆向调试完成端口回包实践总结
  9. 现代软件工程 第三章 【软件工程师的成长】练习与讨论
  10. 金坛区实验幼儿园服务器不稳定,2019年金坛城区部分公办幼儿园服务区划分方案(试行)...