当前位置: 首页 > news >正文

Postgresql源码(118)elog/ereport报错跳转功能分析

1 日志接口

elog.c完成PG中日志的生产、记录工作,对外常用接口如下:

1.1 最常用的ereport和elog

ereport(ERROR,(errcode(ERRCODE_UNDEFINED_TABLE),errmsg("relation \"%s\" does not exist",relation->relname)));
elog(ERROR, "unexpected enrtype: %d", enrmd->enrtype);

其实都是在调用errstart和errfinish函数完成具体工作。

#define elog(elevel, ...)  \ereport(elevel, errmsg_internal(__VA_ARGS__))#define ereport(elevel, ...)	\ereport_domain(elevel, TEXTDOMAIN, __VA_ARGS__)#define ereport_domain(elevel, domain, ...)	\do { \pg_prevent_errno_in_scope(); \if (__builtin_constant_p(elevel) && (elevel) >= ERROR ? \errstart_cold(elevel, domain) : \errstart(elevel, domain)) \__VA_ARGS__, errfinish(__FILE__, __LINE__, __func__); \if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \pg_unreachable(); \} while(0)

2 日志数据结构

  • 单条日志被抽象为ErrorData,记录了日志的全部信息。
  • elog.c提供了一个深度为5的stack来存放最多五层的ErrorData,大部分场景下,stack只会使用一层:
#define ERRORDATA_STACK_SIZE  5
static ErrorData errordata[ERRORDATA_STACK_SIZE];

在这里插入图片描述

3 日志的工作流程

每一条日志都是经过errstart和errfinish函数处理的,分工大致为:

  • errstart
    1. 在errdata堆栈中压入一个新的edata
    2. 为edata填充部分错误信息,例如错误等级、需要输出到server/client、按需升级错误等级(例如Crit区域中大于等于ERROR的需要变成PINIC)
  • errfinish
    1. 在进入errfinish前,错误信息的文本经过errmsg或errmsg_internal函数中的EVALUATE_MESSAGE宏记入edata中的message中,内存用的是errfinish
    2. 三部分工作:
      • 3.1 完成PG_TRY()、PG_CATCH()跳转功能,为errfinish添加try/catch功能
      • 3.2 完成error_context_stack的回调功能,为errfinish增加报错信息
      • 3.3 完成EmitErrorReport,为errfinish发送错误信息

3.1 完成PG_TRY()、PG_CATCH()跳转功能,为errfinish添加try/catch功能

注意PG_CATCH和PG_FINALLY是二选一的,区别是PG_FINALLY会在最后把异常重新抛出去,而PG_CATCH自己处理完了就不在向上抛了。

#define PG_TRY()  \do { \sigjmp_buf *_save_exception_stack = PG_exception_stack; \ErrorContextCallback *_save_context_stack = error_context_stack; \sigjmp_buf _local_sigjmp_buf; \bool _do_rethrow = false; \if (sigsetjmp(_local_sigjmp_buf, 0) == 0) \{ \PG_exception_stack = &_local_sigjmp_buf#define PG_CATCH(...)	\} \else \{ \PG_exception_stack = _save_exception_stack; \error_context_stack = _save_context_stack#define PG_FINALLY() \} \else \_do_rethrow = true; \{ \PG_exception_stack = _save_exception_stack; \error_context_stack = _save_context_stack#define PG_END_TRY()  \} \if (_do_rethrow) \PG_RE_THROW(); \PG_exception_stack = _save_exception_stack; \error_context_stack = _save_context_stack; \} while (0)

我们先看一个PG中常规的报错流程,注意是不在PG_TRY中的elog(ERROR),发生>=ERROR级别的异常后,在errfinish中会抛出异常,jmp到PostgresMain函数中的sigsetjmp的位置,进入异常回收流程。
在这里插入图片描述
那么如果代码中的报错被PG_TRY、PG_CATCH包裹时,抛出异常会发生什么呢?
在这里插入图片描述

3.2 完成error_context_stack的回调功能,为errfinish增加报错信息

error_context_stack是一个Lisrt记录了回调函数回调函数的参数,这里的函数的作用是添加报错信息,因为这些函数会在errfinish时被调用,函数中往往都会使用errcontext_msg记录一些更详细的报错文本。

typedef struct ErrorContextCallback
{struct ErrorContextCallback *previous;void		(*callback) (void *arg);void	   *arg;
} ErrorContextCallback;extern PGDLLIMPORT ErrorContextCallback *error_context_stack;

例如pl编译时配置的plpgsql_compile_error_callback函数,为了增加编译报错时,错误的发生的位置等:

do_compile...plerrcontext.callback = plpgsql_compile_error_callback;plerrcontext.arg = forValidator ? proc_source : NULL;plerrcontext.previous = error_context_stack;error_context_stack = &plerrcontext;...
static void
plpgsql_compile_error_callback(void *arg)
{if (arg){/** Try to convert syntax error position to reference text of original* CREATE FUNCTION or DO command.*/if (function_parse_error_transpose((const char *) arg))return;/** Done if a syntax error position was reported; otherwise we have to* fall back to a "near line N" report.*/}if (plpgsql_error_funcname)errcontext("compilation of PL/pgSQL function \"%s\" near line %d",plpgsql_error_funcname, plpgsql_latest_lineno());
}

error_context_stack和上面提到的PG_exception_stack都会在TRY中进行保存和恢复,为什么:

  • PG_exception_stack比较好理解,因为TRY时会建一个新的jmpbuf用PG_exception_stack指向,之前的旧值需要记录下来,TRY完了需要恢复。
  • error_context_stack的回调函数是在子模块中配置的,正常执行完子模块会把error_context_stack恢复原样,但一旦error发生了跳转,恢复逻辑就被跳过了。所以在TRY中自带了恢复error_context_stack的逻辑。

3.3 完成EmitErrorReport,为errfinish发送错误信息

errfinish......EmitErrorReport......

EmitErrorReport函数中会执行发送逻辑:

EmitErrorReport...if (edata->output_to_server && emit_log_hook)(*emit_log_hook) (edata);/* Send to server log, if enabled */if (edata->output_to_server)send_message_to_server_log(edata);    // 写 write_syslog/* Send to client, if enabled */if (edata->output_to_client)send_message_to_frontend(edata);      // 写libpq,发送到客户端或主进程

4 CopyErrorData / FlushErrorState / FreeErrorData

由于edata中的信息是在ErrorContext中申请的,在PG_CATCH时,是能拿到edata使用的,但在catch时不应该使用ErrorContext申请任何内存,所以惯用法是在PG_CATCH中用CopyErrorData把edata拷贝到当前的上下文中,在进行操作。然后把ErrorContext中的edata用FlushErrorState清理干净。

例如PL中的用法

		PG_CATCH();{ErrorData  *edata;....../* Save error info in our stmt_mcontext */MemoryContextSwitchTo(stmt_mcontext);// 拷贝edata到当前上下文中edata = CopyErrorData();// ErrorContext中的用完尽快释放FlushErrorState();......// 尽情使用使用edataexception_matches_conditions(edata, exception->conditions)......	

相关文章:

Postgresql源码(118)elog/ereport报错跳转功能分析

1 日志接口 elog.c完成PG中日志的生产、记录工作,对外常用接口如下: 1.1 最常用的ereport和elog ereport(ERROR,(errcode(ERRCODE_UNDEFINED_TABLE),errmsg("relation \"%s\" does not exist",relation->relname)));elog(ERRO…...

Python Selenium中的强大等待设置详解

更多资料获取 📚 个人网站:ipengtao.com 在Web自动化测试中,等待是至关重要的一环,而Selenium提供了丰富的等待设置来确保测试脚本的可靠性和稳定性。本文将深入研究Python Selenium中常用的必备等待设置,包括显式等待…...

ACL实现固定时间访问资源——项目

文章目录 一、前言二、项目拓扑三、项目需求四、配置思路五、配置步骤1 IP地址2 端口类型3 静态路由4 流策略 六、结语 免责声明 本文旨在提供信息和解决问题的建议,观点和建议可能不适用于个人情况,仅供参考!!! 文章中…...

前端学习——关于前端框架的思考

前端框架 我们知道在AngularJS,react,vue等前端框架出现之前,前端开发都是通过js直接操作dom树来实现的,而有了前端框架之后,前端开发基本上不需要在直接操作dom树,相当于在原生html的dom树之间和前端程序…...

大创项目推荐 深度学习+opencv+python实现车道线检测 - 自动驾驶

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数:3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &am…...

Linux(二)常用命令

文章目录 一、文件管理命令1.1 chmod1.2 chown1.3 cat1.4 cp1.5 find1.6 head1.7 tail1.8 less1.9 more1.10 mv1.11 rm1.12 touch1.13 vim1.14 >和>>1.15 scp1.16 ln1.17 怎么用命令查看日志 二、文档管理命令2.1 grep2.2 wc2.3 echo 三、磁盘管理命令3.1 cd3.2 df3.3…...

PHP通过mailer发送邮箱

<?php namespace sw\controler\action;require(APP_DIR./extend/PHPMailer/class.phpmailer.php); require(APP_DIR./extend/PHPMailer/class.smtp.php); class action_test_mailer extends Base {public function test(){$smtpemailto"1967899707qq.com";//接收…...

c# OpenCV 基本绘画(直线、椭圆、矩形、圆、多边形、文本)(四)

我们将在这里演示如何使用几何形状和文本注释图像。 Cv2.Line() 绘制直线 Cv2.Ellipse() 绘制椭圆Cv2.Rectangle() 绘制矩形Cv2.Circle() 绘制圆Cv2.FillPoly() 绘制多边形Cv2.PutText() 绘制文本 一、绘制直线 Cv2.Line(image, start_point, end_point, color, thickness) …...

js键盘事件keydown事件,防止重复触发,组合键的配合使用

js键盘事件keydown事件&#xff0c;防止重复触发 键盘事件类型主要有三种&#xff1a; keydown 、keypress(不建议使用&#xff0c;部分浏览器已放弃)和 keyup 。 添加普通键盘keydown事件 // 监听键盘按下事件document.addEventListener(keydown, function(event) {// 输出按…...

【Docker】升级docker或者docker到docker-ce完全保留镜像和容器,不影响原容器使用方法

升级docker或者docker到docker-ce完全保留镜像和容器&#xff0c;不影响原容器使用方法 一、介绍二、升级方法 三、遇到问题说明 以下是我的使用场景&#xff0c;docker升级到docker-ce&#xff0c;但对于docker-ce升级也通用&#xff01;亲测&#xff01; 一、介绍 CentOS自带…...

22 3GPP在SHF频段基于中继的5G高速列车场景中的标准化

文章目录 信道模型实验μ参考信号初始接入方法波形比较 RRH&#xff1a;remote radio head 远程无线头 HTS&#xff1a;high speed train 高速移动列车 信道模型 考虑搭配RRH和车载中继站之间的LOS路径以及各种环境&#xff08;开放或峡谷&#xff09;&#xff0c;在本次实验场…...

C语言之初识C语言

文章目录 前言一、什么是C语言二、第一个C语言程序三、数据类型四、变量&#xff0c;常量1、变量1.1 变量的命名1.2 变量的分类1.3 变量的使用1.4 变量的作用域和生命周期2、变量 五、字符串1. 概念2. 求解字符串的长度【strlen】3. 转义字符【含笔试题】 六、注释七、选择语句…...

Modbus-TCP数据帧

Modbus-TCP基于4种报文类型 MODBUS 请求是客户机在网络上发送用来启动事务处理的报文MODBUS 指示是服务端接收的请求报文MODBUS 响应是服务器发送的响应信息MODBUS 证实是在客户端接收的响应信息 Modbus-TCP报文: 报文头MBAP MBAP为报文头&#xff0c;长度为7字节&#xff0c…...

linux搭建gitlab

gitlab的介绍 区别于github&#xff0c;github是面向互联网基于git实现的代码托管平台&#xff0c;gitlab是基于Ruby语言实现的git管理平台软件&#xff0c;一般用于公司内部代码仓库。 gitlab组成 Nginx 静态Web服务器Gitlab-workhorse 轻量级的反向代理服务器Gitlab-shell 用…...

GEM5 Garent CPU cache消息传递路径:1. NI部分

简介 我们仔细分析下图怎么连的&#xff0c;以及消息传递路径。 图来自https://www.gem5.org/documentation/general_docs/ruby/ 代码的连接 fs.py->ruby.py-> gem5/configs/ruby/MESI_Two_Level.py 中的 create_system( options, full_system, system, dma_ports, b…...

Java设计模式之单例模式以及如何防止通过反射破坏单例模式

单例模式 单例模式使用场景 ​ 什么是单例模式&#xff1f;保障一个类只能有一个对象&#xff08;实例&#xff09;的代码开发模式就叫单例模式 ​ 什么时候使用&#xff1f; 工具类&#xff01;&#xff08;一种做法&#xff0c;所有的方法都是static&#xff0c;还有一种单…...

python flask+vue实现前后端图片上传

python flaskvue实现前后端图片上传 vue代码如下&#xff1a; <template><div><input type"file" change"handleFileChange"/><button click"uploadFile">上传</button><br><img :src"imageUrl&…...

centos7安装开源日志系统graylog5.1.2

安装包链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1Zl5s7x1zMWpuKfaePy0gPg?pwd1eup 提取码&#xff1a;1eup 这里采用的shell脚本安装&#xff0c;脚本如下&#xff1a; 先使用命令产生2个参数代入到脚本中&#xff1a; 使用pwgen生成password_secret密码 …...

5G+云渲染技术:将如何快速推进XR和元宇宙?

XR&#xff08;扩展现实&#xff09;领域正在以惊人的速度增长。目前&#xff0c;到 2024 年&#xff0c;一些专家表示这个行业的价值将达到 3000 亿美元。 这个行业发展如此迅速的部分原因是 XR 将在商业环境中的带来巨大利益。近年来&#xff0c;很多企业遇到了将增强现实和…...

【leetcode234】回文链表Java代码讲解

12.21 234. 回文链表 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#xff1a; 输入&a…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...