【中间件】brpc_基础_用户态线程中断

bthread之用户态线程中断

源码

1 简介

interrupt_pthread 核心功能是 通过信号机制中断阻塞的 pthread 线程,以实现线程的协作式中断。


2 核心功能与设计

2.1 信号选择与注册

  • 信号选择:使用 SIGURG 作为中断信号。
    • 原因SIGURG 通常用于处理带外数据(Out-of-Band Data),在常规应用中极少被使用,避免与其他信号冲突。
    • 空处理函数do_nothing_handler 不做任何操作,仅用于触发信号机制。
    void do_nothing_handler(int) {} // 空信号处理器
    

2.2 线程安全初始化

  • 一次性注册:通过 pthread_once 确保 SIGURG 的信号处理函数 仅注册一次,避免多线程环境下的重复注册。
    static pthread_once_t register_sigurg_once = PTHREAD_ONCE_INIT;
    static void register_sigurg() {signal(SIGURG, do_nothing_handler);
    }
    

2.3 中断线程

  • 发送信号interrupt_pthread 向目标线程发送 SIGURG 信号,触发中断。
    int interrupt_pthread(pthread_t th) {pthread_once(&register_sigurg_once, register_sigurg);return pthread_kill(th, SIGURG);
    }
    

3 关键机制解析

3.1 中断阻塞的系统调用

  • EINTR 触发:当目标线程阻塞在某个系统调用(如 read, write, sleep)时,SIGURG 会中断该调用,使其返回 EINTR 错误码,线程得以继续执行后续逻辑。
  • 协作式中断:线程需检查 EINTR 并决定是否退出,非强制终止,避免资源泄漏。

3.2 与 bthread 的集成

  • 用户态线程支持bthread 可能运行在 pthread 之上,中断 pthread 会影响其管理的所有 bthread
  • 用途:通常用于:
    • 优雅停止服务(如取消长时间阻塞的任务)。
    • 处理超时或取消请求。

4 潜在问题与注意事项

4.1 信号冲突

  • 确保 SIGURG 未被占用:若应用其他模块使用了 SIGURG,会导致行为冲突。需在项目全局范围内约定信号用途。
  • 替代方案:可自定义信号(如 SIGUSR1),但需确保跨平台兼容性。

4.2 可移植性

  • POSIX 依赖:依赖 pthread_killsignal,在非 POSIX 系统(如 Windows)不可用。
  • 信号处理差异:不同 Unix 系统对信号的处理细节可能不同,需充分测试。

4.3 中断后的处理

  • 错误检查:被中断的线程需检查系统调用的返回值,处理 EINTR
    int ret = read(fd, buf, size);
    if (ret == -1 && errno == EINTR) {// 被中断,执行清理或重试
    }
    
  • 资源清理:确保信号中断后释放锁、关闭文件描述符等资源,避免死锁或泄漏。

4.4 性能影响

  • 信号处理开销:频繁发送信号可能导致性能下降,尤其在多线程高并发场景。
  • 替代方案:考虑使用事件驱动模型(如 epoll)避免阻塞调用。

5 典型应用场景

  1. 服务优雅退出
    void* worker_thread(void* arg) {while (!stopped) {int ret = accept(...);if (ret == -1 && errno == EINTR) {break; // 收到中断信号,退出循环}// 处理请求}
    }
    
  2. 任务超时控制
    // 设置超时后调用 interrupt_pthread
    set_timeout(100ms, [] { interrupt_pthread(target_thread); });
    

6 总结

函数作用
do_nothing_handler空信号处理函数,仅触发 EINTR
register_sigurg_once确保信号注册的线程安全
interrupt_pthread发送 SIGURG 中断目标线程的阻塞操作

该机制通过轻量级信号实现线程协作式中断,是 bthread 库中处理阻塞操作的关键设计,但需谨慎处理信号冲突与错误恢复,确保系统稳定性。

7 延伸

7.1 SIGURG (Urgent Condition Signal)

SIGURG 是 POSIX 标准定义的信号之一,通常用于处理 带外数据(Out-of-Band Data, OOB)
在 TCP 通信中,带外数据用于传输紧急消息(如 TCP Urgent Pointer),但现代网络编程中极少使用此机制,因此 SIGURG 常被保留或用于其他特定用途。

  • 信号编号:在大多数 Unix 系统(如 Linux、macOS)中,SIGURG 的编号为 23
  • 默认行为:默认忽略(SIG_IGN),除非进程显式注册处理函数。

在 BRPC/bthread 中的用途
在 Apache BRPC 的 bthread 库中,SIGURG 被设计为一种 协作式中断信号,用于中断阻塞在系统调用(如 readacceptsleep 等)的线程。

其核心机制如下:

  1. 触发 EINTR
    • 当向目标线程发送 SIGURG 时,若该线程正在执行阻塞系统调用,系统调用会被中断并返回错误码 EINTR
    • 示例场景
// 线程阻塞在 read 调用
ssize_t ret = read(fd, buf, size);
if (ret == -1 && errno == EINTR) {// 被 SIGURG 中断,执行清理或退出逻辑
}
  1. 信号处理函数

    • 空处理函数do_nothing_handler 不执行任何操作,仅用于触发信号机制。
    void do_nothing_handler(int) {} // 仅用于触发 EINTR
    
    • 避免副作用:由于不修改全局状态,确保信号处理符合 异步信号安全(Async-Signal-Safe) 要求。
  2. 优势

    • 低侵入性SIGURG 默认未被应用占用,减少与其他模块的冲突。
    • 高效性:信号处理开销极小,仅触发中断,无额外逻辑。

潜在风险与注意事项

  1. 信号冲突
  • 问题:若应用其他模块(如自定义网络库)使用 SIGURG,会导致行为冲突。
  • 解决方案
    1. 代码审查:全局检查代码中 SIGURG 的使用情况。
    2. 替换信号:修改 BRPC 源码,改用其他信号(如 SIGUSR1)。
      // 修改信号注册代码
      signal(SIGUSR1, do_nothing_handler); // 替换 SIGURG
      
  1. 平台兼容性
  • Unix 专属SIGURG 在 Windows 中不存在,需通过其他机制(如 Event 或 IOCP)实现中断。
  1. 多线程信号传递
  • 精准控制pthread_kill 可定向发送信号到特定线程,避免全局影响。
  • 竞态条件:需确保目标线程未退出,否则可能触发未定义行为。

替代方案对比

方案优点缺点
SIGURG低冲突、轻量级依赖信号机制,平台限制
SIGUSR1/SIGUSR2用户自定义,无标准冲突可能被其他库占用
Eventfd + epoll无信号开销,兼容性好需修改阻塞逻辑为异步 I/O
Pipe 自中断完全可控,跨平台额外文件描述符,复杂度高

实践建议

  1. 确保信号安全
  • 代码审查:在项目中禁止随意使用 SIGURG
  • 文档标注:明确 SIGURG 被 BRPC 用于中断机制。
  1. 处理 EINTR
  • 重试逻辑:在关键系统调用中循环处理 EINTR
    while (true) {ssize_t ret = read(fd, buf, size);if (ret >= 0) break;if (errno != EINTR) { /* 处理其他错误 */ }
    }
    
  1. 调试与监控
  • 信号跟踪:使用 strace 监控信号传递:
    strace -e signal=SIGURG -p <PID>
    
  • 日志记录:在信号处理函数中添加日志(需确保异步安全):
    void handler(int sig) {const char msg[] = "SIGURG received\n";write(STDERR_FILENO, msg, sizeof(msg)-1);
    }
    

总结
SIGURG 在 BRPC 中作为一种轻量级中断信号,通过触发 EINTR 实现线程协作式中断,但其使用需严格避免冲突。开发者应结合应用场景权衡信号机制与其他中断方案,确保系统稳定性和跨平台兼容性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/904169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 的网络卡

#本机操作系统CentOS 10 #核心版本 rootbogon:/etc# uname -r 6.12.0-65.el10.x86_64 网卡能不能被捉到可以使用【dmesg|grep xx】来判断&#xff0c;有没有驱动则可以使用lsmod看看模块有没有加载核心&#xff01;最后&#xff0c;以ifconfig xxx测试看看 观察核心所捉到的网卡…

前端双工通信的几种方案详细描述

前端实现双工通信&#xff08;全双工或半双工&#xff09;的常见方案及详细实现如下&#xff1a; 一、WebSocket&#xff08;全双工&#xff09; 原理&#xff1a;基于 TCP 的持久化协议&#xff0c;客户端与服务端建立双向通信通道&#xff0c;支持实时双向数据传输。 // 客…

KUKA机器人快速启动设置

KUKA机器人在首次开机启动时&#xff0c;有时在示教器上需要进行投入运行等相关的设置。如以下相关的信息需要处理&#xff1a; 1、机器人系统开机后&#xff0c;选择T1运行模式&#xff1b;2、显示提示信息&#xff1a;“RDC 存储器和控制系统不一致什么被更换了”时&#xf…

游戏代码C

以下将结合不同编程语言的特点及游戏开发中的实际应用&#xff0c;展示多种语言的游戏代码示例&#xff08;以简单游戏为例&#xff0c;展示代码结构和逻辑差异&#xff09;。由于代码篇幅较长&#xff0c;我将分语言进行说明并引用相关来源&#xff1a; 1. C# Unity&#xff…

LangChain Agent核心解析:Zero-Shot-ReAct策略实现与实战指南

引言 在LangChain的Agent框架中&#xff0c;zero-shot-react-description 是一种预定义的Agent类型&#xff0c;它结合了Zero-Shot&#xff08;零样本学习&#xff09; 和 ReAct&#xff08;推理行动&#xff09; 策略&#xff0c;主要用于根据工具的描述动态选择和执行工具&a…

PyQt 或 PySide6 进行 GUI 开发文档与教程

一、官网文档 Qt 官方文档&#xff1a;Porting to Qt 6 | Qt 6.9Qt 维基&#xff1a;​​​​​​​Qt WikiQt for Python (PySide6) &#xff1a;​​​​​​​Qt for Python - Qt WikiPySide6 快速上手指南&#xff1a;​​​​​​​Getting Started - Qt for Python PyS…

2024年第十五届蓝桥杯省赛B组Python【 简洁易懂题解】

2024年第十五届蓝桥杯省赛B组Python题解 一、整体情况说明 2024年第十五届蓝桥杯省赛B组Python组考试共包含8道题目&#xff0c;分为结果填空题和程序设计题两类。 考试时间&#xff1a;4小时编程环境&#xff1a;Python 3.x&#xff0c;禁止使用第三方库&#xff0c;仅可使…

Go语言--语法基础4--基本数据类型--类型转换

Go 是一种强类型的语言&#xff0c;所以如果在赋值的时候两边类型不一致会报错。一个类型的值可以被转换成另一种类型的值。由于 Go 语言不存在隐式类型转换&#xff0c;因此所有的类型转换都必须显式的声明。 强制类型转换语法 使用 type (a) 这种形式来进行强制类型转换&am…

nginx 代理时怎么更改 Remote Address 请求头

今天工作中遇到用 localhost 访问网站能访问后台 api&#xff0c;但是用本机IP地址后就拒绝访问&#xff0c;我怀疑是后台获取 Remote Address 然后设置白名单了只能 localhost 访问。 想用 nginx 更改 Remote Address server {listen 8058;server_name localhost;loca…

LeetCode刷题链表

文章目录 链表总结 常用技巧两数相加题解代码 两两交换链表中的节点题解代码 重排链表题解代码 合并k个升序链表题解代码 K个一组翻转链表题解代码 链表总结 常用技巧 画图 直观 形象 便于理解引入虚拟头节点&#xff0c;便于处理边界情况&#xff0c;方便我们对链表进行…

ESP32S3 多固件烧录方法、合并多个固件为单一固件方法

ESP32S3 多固件烧录方法、合并多个固件为单一固件方法 文章目录 ESP32S3 多固件烧录方法、合并多个固件为单一固件方法前言1、前期准备工作2、多固件烧录方法3、单固件烧录方法总结 前言 使用正点原子的ESP32S3 BOX开发板独立烧录编译生成的xxx.bin固件无法正常运行起来&#…

Webug4.0靶场通关笔记10- 第14关链接注入

目录 第14关 链接注入 1.打开靶场 2.源码分析 3.渗透实战 &#xff08;1&#xff09;方法1&#xff1a;跳转外部网页 &#xff08;2&#xff09;方法2&#xff1a;获取cookie 4.漏洞防御 本文通过《webug靶场第14关 链接注入》来进行渗透实战。 第14关 链接注入 链接注…

SpringBoot的汽车商城后台管理系统源码开发实现

概述 汽车商城后台管理系统专为汽车4S店和经销商设计&#xff0c;提供全面的汽车管理系统解决方案。 主要内容 1. 核心功能模块 系统提供以下主要功能&#xff1a; ​​销售管理​​&#xff1a;记录销售信息&#xff0c;跟踪交易进度​​客户管理​​&#xff1a;维护客户…

VBA代码解决方案第二十四讲:EXCEL中,如何删除重复数据行

《VBA代码解决方案》(版权10028096)这套教程是我最早推出的教程&#xff0c;目前已经是第三版修订了。这套教程定位于入门后的提高&#xff0c;在学习这套教程过程中&#xff0c;侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码…

日本IT行业|salesforce开发语言占据的地位

在日本的IT行业中&#xff0c;Salesforce 开发语言处于一个较为专业但稳步增长的细分领域&#xff0c;并不是主流开发语言&#xff08;如 Java、Python、PHP&#xff09;&#xff0c;但其在某些行业和场景中地位越来越重要。 本篇以下是详细分析&#xff1a; Salesforce开发语言…

前端开发,文件在镜像服务器上不存在问题:Downloading binary from...Cannot download...

问题与处理策略 问题描述 在 Vue 项目中&#xff0c;执行 npm i 下载依赖时&#xff0c;报如下错误 Downloading binary from https://npm.taobao.org/mirrors/node-sass//v4.14.1/win32-x64-72_binding.node Cannot download "https://npm.taobao.org/mirrors/node-sa…

基于Vue2 + Element 实现任务列表管理功能的详细教程

前言&#xff1a;本文介绍的是如何从0开始搭建Vue2项目到1实现对任务添加、删除和筛选的功能&#xff0c;&#x1f517; 相关链接Vue 入门(安装与应用超详细教程) ❤ 【作者主页—&#x1f4da;阅读更多优质文章、获取更多优质源码】 目录 一 . 项目搭建 1.1 安装node.js 1.…

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】1.4 数据库与表的基本操作(DDL/DML语句)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 1.4 数据库与表的基本操作&#xff08;DDL/DML语句&#xff09;1.4.1 数据库生命周期管理&#xff08;DDL核心&#xff09;1.4.1.1 创建数据库&#xff08;CREATE DATABASE&…

Fabrice Bellard(个人网站:‌bellard.org‌)介绍

Fabrice Bellard 是法国人&#xff0c;国际著名程序员。1972年生于法国Grenoble&#xff0c;大学就读于巴黎高等综合理工学院&#xff0c;后在国立巴黎高等电信学院攻读。 Fabrice Bellard&#xff08;个人网站&#xff1a;‌bellard.org‌&#xff09;是计算机领域最具影响力…

USB布局布线

1USB简介 USB是通用串行总线的英文缩写&#xff0c;是连接外部装置的一个串口总线标准&#xff0c;也是一种输入输出接口的技术规范&#xff0c;被广泛地应用于个人电脑和移动设备等信息通迅产品&#xff0c;并扩展到摄影器材&#xff0c;数字电视&#xff08;机顶盒&#xff0…