Impala实践:解析glog打印的 C++ 报错堆栈

news2025/1/9 17:02:11

Impala实践:解析glog打印的 C++ 报错堆栈

Impala使用glog生成日志。生产环境用的都是release build,glog产生的报错堆栈里没有函数名,很难像Java报错堆栈那样方便定位问题。下面是 Impalad 日志中的一个报错:

I0522 09:07:16.002056 20222 status.cc:128] Snappy: RawUncompress failed
    @           0xae26c9
    @          0x107635b
    @          0x11b1f2d
    @          0x11b23ef
    @          0x11af96f
    @          0x11b096b
    @          0x11b2b31
    @          0x118644b
    @          0x11774c2
    @          0x1178805
    @          0x1100f31
    @          0x1101a79
    @          0x16a3449
    @     0x7f257f7ebea4
    @     0x7f257f5148dc
I0522 09:07:16.002146 20222 hdfs-scan-node.cc:512] Scan node (id=0) ran into a parse error for scan range abfss://xxx

从文本只能看出来是id=0的scan node在读ABFS上一个文件时发生了snappy解压失败,并不清楚具体是怎么发生的。好在如上的堆栈提供了代码地址,只要把可执行文件反汇编出来,很多函数名还是可以找到的。下面就以这个堆栈为例,介绍如何手动解析函数名。

1. 反汇编

首先找到impalad可执行文件,可以查看当前正在运行的impalad进程,在命令中找到可执行文件:

$ ps aux | grep impalad
impala     78554  8.0  0.2 10490904 630020 ?     Sl   04:42  12:48 /opt/cloudera/parcels/CDH-6.3.x-1.cdh6.3.x.p0.34479352/lib/impala/sbin-retail/impalad --flagfile=/var/run/cloudera-scm-agent/process/304-impala-IMPALAD/impala-conf/impalad_flags
root      133407  0.0  0.0  10692   976 pts/0    S+   07:20   0:00 grep --color=auto impalad

上面得到的可执行文件是 /opt/cloudera/parcels/CDH-6.3.x-1.cdh6.3.x.p0.34479352/lib/impala/sbin-retail/impalad。一般在CDH/CDP机器上,impalad可执行文件都在这个目录里: /opt/cloudera/parcels/CDH/lib/impala/sbin-retail/
其中 /opt/cloudera/parcels/CDH 是个软链,指向了当前生效的parcel解压目录。

把impalad可执行文件反汇编,使用 objdump 指令,把反汇编代码输出到 /tmp/impalad.asm

cd /opt/cloudera/parcels/CDH/lib/impala/sbin-retail/
objdump -drwC -Mintel impalad > /tmp/impalad.asm

2. 搜索指令地址

按堆栈里的地址在汇编代码里搜索。比如上面第一个地址是 0xae26c9,把前缀 0x 去掉,查找它+1的地址,即地址为ae26ca的代码(注:十六进制里 9+1=a,如果impala使用的是gcc-10及以上版本则不需要加1):
在这里插入图片描述
这里的第一列就是代码地址,图里的第一行是函数的定义。0xae26ca是一个 lea 指令,其往上一行是个 call 指令,栈里保存的其实就是函数调用后的返回地址,也就是 call 指令的下一行地址0xae26ca。因此我们得知,最上一层是在调用 impala::GetStackTrace() 函数,所在函数是 impala::Status::Status(std::string const&)。

同理处理 0x107635b,它加一的地址为 0x107635c,也能在汇编代码里搜到:
在这里插入图片描述
它的上一个指令确实是调用 impala::Status::Status() 的 call 指令,当前指令所在的函数是

impala::SnappyDecompressor::ProcessBlock(bool, long, unsigned char const*, long*, unsigned char**)

再比如0x11b23ef,它加一的地址是 0x11b23f0,同样可以在反汇编代码中找到:
在这里插入图片描述
所在函数是 impala::HdfsTextScanner::FillByteBuffer(impala::MemPool*, bool*, int)

用这样的方法可以手动解析出好几个函数名,这基本上就跟debug build得到的堆栈一样了:

      0xae26c9 impala::Status::Status(std::string const&)
     0x107635b impala::SnappyDecompressor::ProcessBlock(bool, long, unsigned char const*, long*, unsigned char**)
     0x11b1f2d impala::HdfsTextScanner::FillByteBufferCompressedFile(bool*)
     0x11b23ef impala::HdfsTextScanner::FillByteBuffer(impala::MemPool*, bool*, int)
     0x11af96f impala::HdfsTextScanner::FillByteBufferWrapper(impala::MemPool*, bool*, int)
     0x11b096b impala::HdfsTextScanner::ProcessRange(impala::RowBatch*, int*)
     0x11b2b31 impala::HdfsTextScanner::GetNextInternal(impala::RowBatch*)
     0x118644b impala::HdfsScanner::ProcessSplit()
     0x11774c2 impala::HdfsScanNode::ProcessSplit(std::vector<impala::FilterContext, std::allocator<impala::FilterContext> > const&, impala::MemPool*, impala::io::ScanRange*, long*)
     0x1178805 impala::HdfsScanNode::ScannerThread(bool, long)
     0x1100f31 impala::Thread::SuperviseThread(…)
     0x1101a79 boost::detail::thread_data<…>::run()
     0x16a3449 thread_proxy
0x7f257f7ebea4
0x7f257f5148dc

但到 0x7f257f7ebea4 会发现找不到代码了,这个是动态链接的地址,只有在运行时把 so 文件加载进来才有。另外类似的还有 codegen 函数的地址,在反汇编代码里也是找不到的,因为 codegen 代码是运行时生成的。大部分指令还是能找到的,不影响使用。

3. 让 glog 打印函数名

其实release build也可以显示解析好函数的堆栈,只需要在启动参数里加上 --symbolize_stacktrace=true 就行了(这其实是 glog 的一个参数)。打开 symbolize_stacktrace 后,使用 release build 产生的报错也就跟 debug build 一样了:

I0723 21:19:43.712909 229706 status.cc:128] Snappy: RawUncompress failed
    @           0xae26c9  impala::Status::Status()
    @          0x107635b  impala::SnappyDecompressor::ProcessBlock()
    @          0x11b1f2d  impala::HdfsTextScanner::FillByteBufferCompressedFile()
    @          0x11b23ef  impala::HdfsTextScanner::FillByteBuffer()
    @          0x11af96f  impala::HdfsTextScanner::FillByteBufferWrapper()
    @          0x11b096b  impala::HdfsTextScanner::ProcessRange()
    @          0x11b2b31  impala::HdfsTextScanner::GetNextInternal()
    @          0x118644b  impala::HdfsScanner::ProcessSplit()
    @          0x11774c2  impala::HdfsScanNode::ProcessSplit()
    @          0x1178805  impala::HdfsScanNode::ScannerThread()
    @          0x1100f31  impala::Thread::SuperviseThread()
    @          0x1101a79  boost::detail::thread_data<>::run()
    @          0x16a3449  thread_proxy
    @     0x7fc522befe24  start_thread
    @     0x7fc522919bac  __clone

4. 总结

Impala C++代码的报错堆栈是使用glog打印的,可以从指令地址手动解析出函数名,也可以在启动参数里加 --symbolize_stacktrace=true 让 glog 打印带符号(函数名)的堆栈。

关注Apache Impala公众号,及时获取更多Impala资讯

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

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

相关文章

浅复制和深复制(使用python)

在编程语言中&#xff0c;复制通常是通过赋值操作来实现的。具体实现方式可能因编程语言而异。 1. 浅复制&#xff08;Shallow Copy&#xff09; 浅复制是指创建一个新对象&#xff0c;新对象的内容是原始对象的引用。换句话说&#xff0c;新对象和原始对象共享相同的数据&am…

【JVM】JVM 调优的参数都有哪些?

文章目录 1. 设置堆空间大小2. 虚拟机栈的设置3. 年轻代中Eden区和两个Survivor区的大小比例4. 年轻代晋升老年代阈值5. 设置垃圾回收收集器 1. 设置堆空间大小 设置堆的初始大小和最大大小&#xff0c;为了防止垃圾收集器在初始大小、最大大小之间收缩堆而产生额外的时间&…

【Linux系统编程】21.echo、env、fork、getpid、getppid

目录 echo PATH SHELL TERM LANG HOME env fork 返回值 getpid getppid 测试代码1 测试结果 测试代码2 测试结果 父子进程相同 父子进程不同 父子进程共享 echo 查看单个环境变量。 PATH 可执行文件的搜索路径。 SHELL 当前Shell。 TERM 当前终端类型。终端…

一休休的面试题

重点面试题(今天又看了很多的博客大概有个三十来篇吧所以总结了一休休的面试题)&#xff1a; ps:已经入秋了为什么还是这么热&#xff01;&#xff01;&#xff01; 1、受管 bean 的生命周期 对于普通的 Java 对象&#xff0c;new 的时候会去创建对象&#xff0c;而当它没有…

Redis进阶(3)——在Linux上基于Docker容器Redis搭建一主二从三哨兵 SpringBoot整合Redis哨兵

目录 引出redis主从搭建&#xff1a;一主2从6389Master准备文件redis.confredis.log日志文件运行容器查看日志方式tail 6390Slave6391Slave 创建3哨兵创建文件夹sentinel创建运行哨兵容器问题&#xff1a;脑裂问题 SpringBoot整合Redis哨兵启动1主2从&#xff0c;3哨兵pom.xml文…

聊聊服务端缓存那些事(预热、淘汰、污染、雪崩、穿透、击穿等)

文章目录 概要一、缓存预热二、缓存污染2.1、先更新数据库再更新缓存2.2、先更新缓存再更新数据库2.3、先删除缓存再更新数据库&#xff0c;读时再更新2.4、先更新数据库再删除缓存&#xff0c;读时再更新2.5、缓存污染总结2.6、删除缓存失败了怎么办&#xff1f;2.7、延迟双删…

【数据结构与算法】十大经典排序算法-堆排序

&#x1f31f;个人博客&#xff1a;www.hellocode.top &#x1f3f0;Java知识导航&#xff1a;Java-Navigate &#x1f525;CSDN&#xff1a;HelloCode. &#x1f31e;知乎&#xff1a;HelloCode &#x1f334;掘金&#xff1a;HelloCode ⚡如有问题&#xff0c;欢迎指正&#…

JZ33二叉搜索树的后序遍历序列

题目地址&#xff1a;二叉搜索树的后序遍历序列_牛客题霸_牛客网 题目回顾&#xff1a; 解题思路&#xff1a; 使用栈 栈的特点是&#xff1a;先进后出。 通读题目后&#xff0c;我们可以得出&#xff0c;二叉搜索树是左子节点小于根节点&#xff0c;右子节点大于根节点。 …

wps设置一键标题字体和大小

参考 wps设置一键标题字体和大小&#xff1a;https://www.kafan.cn/A/7v5le1op3g.html 统一一键设置

[FPGA IP系列] 2分钟了解FPGA中的BRAM

FPGA设计中&#xff0c;BRAM是一项非常关键的内置存储资源&#xff0c;FPGA开发需要熟练使用BRAM&#xff0c;今天再复习一下BRAM的知识&#xff0c;包括BRAM的定义、组成、应用等等。 一、BRAM介绍 1、BRAM的定义 RAM是Random Access Memory&#xff0c;也就是随机访问数据…

C字符串练习题(6.3.1)

编写一个程序&#xff0c;从键盘上读入一个小于1000的正整数&#xff0c;然后创建并输出一个字符串&#xff0c;说明该整数的值。例如&#xff0c;输入941&#xff0c;程序产生的字符串是“Nine hundred and forty one”。 #include<stdlib.h> #include<string.h>…

【STM32】FreeRTOS互斥量学习

互斥量&#xff08;Mutex&#xff09; 互斥量又称互斥信号量&#xff08;本质也是一种信号量&#xff0c;不具备传递数据功能&#xff09;&#xff0c;是一种特殊的二值信号量&#xff0c;它和信号量不同的是&#xff0c;它支持互斥量所有权、递归访问以及防止优先级翻转的特性…

Spring Boot 项目实现 Spring AOP

【注】实现在SpringBoot项目中&#xff0c;同时给两个类的方法添加AOP前置通知 1、创建一个SpringBoot项目 2、创建两个目标类和方法 package com.tqazy.learn_spring_project.spring_aop;import org.springframework.stereotype.Service;/*** ClassName SpringAopUserServi…

【树状数组优化哈希DP】CF1801 C

Problem - C - Codeforces 思路&#xff1a; Code&#xff1a; #include <bits/stdc.h>#define lowbit(x) (x & (-x))using i64 long long;constexpr int N 2e5 10; constexpr int mod 1e9 7;std::vector<int> V[N];int n, m, x, mxv 0; int a[N], id[N…

MySQL入门学习教程(一)

mysql简介 1、什么是数据库 &#xff1f; 数据库&#xff08;Database&#xff09;是按照数据结构来组织、存储和管理数据的仓库&#xff0c;它产生于距今六十多年前&#xff0c;随着信息技术和市场的发展&#xff0c;特别是二十世纪九十年代以后&#xff0c;数据管理不再仅仅…

学习笔记整理-JS-02-基本类型

文章目录 一、数据类型简介和检测1. JavaScript中两大数据类型 二、基本数据类型1. 数字类型2. 字符串类型3. 布尔类型4. undefined类型5. null 三、数据类型的转换1. 数据类型的转换 四、重点内容 一、数据类型简介和检测 1. JavaScript中两大数据类型 基本数据类型 Number S…

Android学习之路(3) 布局

线性布局LinearLayout 前几个小节的例程中&#xff0c;XML文件用到了LinearLayout布局&#xff0c;它的学名为线性布局。顾名思义&#xff0c;线性布局 像是用一根线把它的内部视图串起来&#xff0c;故而内部视图之间的排列顺序是固定的&#xff0c;要么从左到右排列&#xf…

最强自动化测试框架Playwright(22)-模拟器

可以使用测试生成器通过仿真生成测试&#xff0c;以便为特定窗口、设备、配色方案生成测试&#xff0c;以及模拟地理位置、语言或时区。测试生成器还可以生成测试&#xff0c;同时保留经过身份验证的状态。 模拟视口大小 Playwright 打开一个浏览器窗口&#xff0c;其视口设置…

电路基础之电容

电容器&#xff08;Capacitor&#xff09;是由两个导体电极之间夹着一个电介质而组成的元件。这两个电极可以是金属板、箔片、涂层等&#xff0c;而电介质则是放置在电极之间的绝缘材料。电容器的基本构成包括以下几个要素&#xff1a; 电极&#xff1a;电容器的电极是两个导体…