以keepalived为例说明程序不能正常被gdb调试的原因

2024-06-15 17:20

本文主要是介绍以keepalived为例说明程序不能正常被gdb调试的原因,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

现象

通过gdb att $keepalived_pid发起对当前运行keepalived的调试;

在放行keepalived继续执行后,想通过Ctrl+C按键中断执行,观察下被调试程序的当前内部状态,
但是,在终端输入Ctrl+C后,导致keepalived被调试进程退出。

gdb无法对keepalived进行正常的调试交互!

结论先行

  • gdbinferior process之间通过ptrace系统调用,以及对signal信号的拦截、传递进行调试交互过程
  • 由终端触发的signal会首先被Kernel路由到inferior process,然后再被gdb截获
  • Linux Kernel针对inferior process信号存在特别的路由机制,会导致某些应用使用了特别信号捕获机制,例如,sigwait or signalfd,并处理了SIGINT信号,则不能被gdb正常调试

缘由

以前就了解到,如果被调试程序使用到类似sigwait特殊的信号捕捉机制,将会导致gdb调试程序遇到麻烦,特别是无法正常使用Ctrl+C按键,中断暂停被调试程序,进行正常的交互操作。

最近遇到keepalived一些问题, 就想用调试的方法看看它的运行时逻辑,在这时就遭遇了现象一样的调试失败。

先搜索了下keepalived源码,并无sigwait的使用过程,因为以前看那篇介绍比较粗,不知道除了sigwait使用方式外,还有signalfd使用方式,也会导致GDB调试遭遇类似问题。
而且,当时觉得keepalived作为比较出名的开源软件,应该不会不支持被调试,所以,并没有在第一时间发现原因。

分析

采用了分掘挖进的方法:

  • 用不同的keepalived版本
  • 用不同的linux部署环境、不同的gdb版本

来分析、验证这个问题,结果发现表象却出奇的一致!

最后,懒得继续研究下去其中到底为什么了,就向keepalived社区提出了Keeppalived不能被正常调试的issue。

社区解决方案

keepalived社区称之为Linux Kernel signal bug,但Linux社区保持这样的信号处理特性,有其原因。

最终,keepalived社区用新增启动参数项--ignore-sigint来解决这个问题。

图解

调试模型
信号调试交互序列图

参考

  • Keeppalived不能被正常调试的issue
  • 社区新增–ignore-sigint option的commit
  • E文 Linux信号路由特殊机制导致GDB正常Ctrl+C却调试失败
  • E文 调试的信号传递过程
  • E文 GNU GDB 信号处理相关命令

这篇关于以keepalived为例说明程序不能正常被gdb调试的原因的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1064087

相关文章

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav

在IntelliJ IDEA中高效运行与调试Spring Boot项目的实战步骤

《在IntelliJIDEA中高效运行与调试SpringBoot项目的实战步骤》本章详解SpringBoot项目导入IntelliJIDEA的流程,教授运行与调试技巧,包括断点设置与变量查看,奠定... 目录引言:为良驹配上好鞍一、为何选择IntelliJ IDEA?二、实战:导入并运行你的第一个项目步骤1

mybatis-plus QueryWrapper中or,and的使用及说明

《mybatis-plusQueryWrapper中or,and的使用及说明》使用MyBatisPlusQueryWrapper时,因同时添加角色权限固定条件和多字段模糊查询导致数据异常展示,排查发... 目录QueryWrapper中or,and使用列表中还要同时模糊查询多个字段经过排查这就导致只要whe

SpringBoot改造MCP服务器的详细说明(StreamableHTTP 类型)

《SpringBoot改造MCP服务器的详细说明(StreamableHTTP类型)》本文介绍了SpringBoot如何实现MCPStreamableHTTP服务器,并且使用CherryStudio... 目录SpringBoot改造MCP服务器(StreamableHTTP)1 项目说明2 使用说明2.1

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

zookeeper端口说明及介绍

《zookeeper端口说明及介绍》:本文主要介绍zookeeper端口说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、zookeeper有三个端口(可以修改)aVNMqvZ二、3个端口的作用三、部署时注意总China编程结一、zookeeper有三个端口(可以

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化