1.Gin源码分析 - 中间件(5)- Recovery
2.Golang源码剖析panic与recover,源码看不懂你打我好了
3.翻译:XDA论坛教程:如何手动编译TWRP Recovery
4.如何刷手机第三方中文TWRP的定制recovery
Gin源码分析 - 中间件(5)- Recovery
Recovery中间件在HTTP请求处理中扮演着关键角色,尤其在处理过程中产生panic时。源码它能够捕获并处理这些异常,定制确保服务的源码稳定性和客户端的正常响应。通过使用gin框架,定制锁机激活源码可以通过两种方式集成Recovery中间件:第一种是源码直接调用gin.New创建引擎时,无需注册Recovery中间件;第二种是定制在调用gin.Default()创建引擎时,内部自动注册Recovery中间件。源码在没有使用Recovery中间件的定制情况下,向服务发送异常请求会导致服务端和客户端出现异常;而使用Recovery中间件后,源码异常被捕获并以友好的定制方式显示异常堆栈,同时客户端收到HTTP 错误。源码
Recovery中间件内部实现通过多种变体接口实现,定制包括CustomRecoveryWithWriter、源码RecoveryWithWriter、CustomRecovery以及Recovery。其中,CustomRecoveryWithWriter提供最底层的形式,允许用户自定义异常输出和恢复处理逻辑。RecoveryWithWriter则提供了Writer参数和一个可选的RecoveryFunc,如果没有定义该函数,则使用defaultHandleRecovery。CustomRecovery和Recovery则分别使用默认的DefaultErrorWriter和defaultHandleRecovery。
Recovery的核心实现通过DefaultErrorWriter和defaultHandleRecovery两个主要部分。DefaultErrorWriter负责设置日志格式为红色字体输出。defaultHandleRecovery方法是整个处理流程的核心,包含捕获、处理异常、生成响应等关键步骤。首先通过recover()方法获取panic信息,判断异常是否由客户端断开连接引起,然后获取异常堆栈、请求头,并根据异常类型和原因进行相应的处理和响应输出。最终,根据处理结果返回HTTP响应,聊天app源码开源如果是异常则返回HTTP ,如果是网络原因则使用Abort方法。
Recovery中间件的实现不仅提供了异常处理的灵活性,还确保了服务的稳定性和客户端的友好体验。通过捕获和处理异常,Recovery中间件能够有效地减少服务中断的可能性,提高系统的健壮性。总结而言,Recovery中间件在处理异常时提供了实用的方法,对于开发稳定、可靠的HTTP服务具有重要意义。
Golang源码剖析panic与recover,看不懂你打我好了
哈喽,大家好,我是asong,今天与大家来聊一聊go语言中的"throw、try.....catch{ }"。如果你之前是一名java程序员,我相信你一定吐槽过go语言错误处理方式,但是这篇文章不是来讨论好坏的,我们本文的重点是带着大家看一看panic与recover是如何实现的。上一文我们讲解了defer是如何实现的,但是没有讲解与defer紧密相连的recover,想搞懂panic与recover的实现也没那么简单,就放到这一篇来讲解了。废话不多说,直接开整。
Go 语言中panic 关键字主要用于主动抛出异常,类似 java 等语言中的 throw 关键字。panic 能够改变程序的控制流,调用 panic 后会立刻停止执行当前函数的剩余代码,并在当前 Goroutine 中递归执行调用方的 defer;
Go 语言中recover 关键字主要用于捕获异常,让程序回到正常状态,类似 java 等语言中的 try ... catch 。recover 可以中止 panic 造成的程序崩溃。它是华文行楷源码下载一个只能在 defer 中发挥作用的函数,在其他作用域中调用不会发挥作用;
recover只能在defer中使用这个在标准库的注释中已经写明白了,我们可以看一下:
这里有一个要注意的点就是recover必须要要在defer函数中使用,否则无法阻止panic。最好的验证方法是先写两个例子:
运行我们会发现example2()方法的panic是没有被recover住的,导致整个程序直接crash了。这里大家肯定会有疑问,为什么直接写recover()就不能阻止panic了呢。我们在 详解defer实现机制(附上三道面试题,我不信你们都能做对)讲解了defer实现原理,一个重要的知识点**defer将语句放入到栈中时,也会将相关的值拷贝同时入栈。**所以defer recover()这种写法在放入defer栈中时就已经被执行过了,panic是发生在之后,所以根本无法阻止住panic。
通过运行结果可以看出panic不会影响defer函数的使用,所以他是安全的。
这里我开了两个协程,一个协程会发生panic,导致程序崩溃,但是只会执行自己所在Goroutine的延迟函数,所以正好验证了多个 Goroutine 之间没有太多的关联,一个 Goroutine 在 panic 时也不应该执行其他 Goroutine 的延迟函数。
其实我们在实际项目开发中,经常会遇到panic问题, Go 的 runtime 代码中很多地方都调用了 panic 函数,对于不了解 Go 底层实现的新人来说,这无疑是挖了一堆深坑。我们在实际生产环境中总会出现panic,但是我们的程序仍能正常运行,这是因为我们的框架已经做了recover,他已经为我们兜住底,比如gin,我们看一看他是怎么做的。
我们先来写个简单的代码,看看他的汇编调用:执行go tool compile -N -l -S main.go就可以看到对应的汇编码了,我们截取部分片段分析:
上面重点部分就是波段图指标源码画红线的三处,第一步调用runtime.deferprocStack创建defer对象,这一步大家可能会有疑惑,我上一文忘记讲个这个了,这里先简单概括一下,defer总共有三种模型,编译一个函数里只会有一种defer模式。在讲defer实现机制时,我们一起看过defer的结构,其中有一个字段就是_panic,是触发defer的作用,我们来看看的panic的结构:
简单介绍一下上面的字段:
上面的pc、sp、goexit我们单独讲一下,runtime包中有一个Goexit方法,Goext能够终止调用它的goroutine,其他的goroutine是不受影响的,goexit也会在终止goroutine之前运行所有延迟调用函数,Goexit不是一个panic,所以这些延迟函数中的任何recover调用都将返回nil。如果我们在主函数中调用了Goexit会终止该goroutine但不会返回func main。由于func main没有返回,因此程序将继续执行其他gorountine,直到所有其他goroutine退出,程序才会crash。
下面就开始我们的重点吧~。
在讲defer实现机制时,我们一起看过defer的结构,其中有一个字段就是_panic,是触发defer的作用,我们来看看的panic的结构:简单介绍一下上面的字段:上面的pc、sp、goexit我们单独讲一下,runtime包中有一个Goexit方法,Goext能够终止调用它的goroutine,其他的goroutine是不受影响的,goexit也会在终止goroutine之前运行所有延迟调用函数,xp系统备份源码Goexit不是一个panic,所以这些延迟函数中的任何recover调用都将返回nil。如果我们在主函数中调用了Goexit会终止该goroutine但不会返回func main。由于func main没有返回,因此程序将继续执行其他gorountine,直到所有其他goroutine退出,程序才会crash。写个简单的例子:运行上面的例子你就会发现,即使在主goroutine中调用了runtime.Goexit,其他goroutine是没有任何影响的。所以结构中的pc、sp、goexit三个字段都是为了修复runtime.Goexit,这三个字段就是为了保证该函数的一定会生效,因为如果在defer中发生panic,那么goexit函数就会被取消,所以才有了这三个字段做保护。看这个例子:
英语好的可以看一看这个: github.com/golang/go/is...,这就是上面的一个例子,这里就不过多解释了,了解就好。
接下来我们再来看一看gopanic方法。
gopanic的代码有点长,我们一点一点来分析:
根据不同的类型判断当前发生panic错误,这里没什么多说的,接着往下看。
上面的代码都是截段,这些部分都是为了判断当前defer是否可以使用开发编码模式,具体怎么操作的就不展开了。
在第三部分进行defer内联优化选择时会执行调用延迟函数(reflectcall就是这个作用),也就是会调用runtime.gorecover把recoverd = true,具体这个函数的操作留在下面讲,因为runtime.gorecover函数并不包含恢复程序的逻辑,程序的恢复是在gopanic中执行的。先看一下代码:
这段代码有点长,主要就是分为两部分:
第一部分主要是这个判断if gp._panic != nil && gp._panic.goexit && gp._panic.aborted { ... },正常recover是会绕过Goexit的,所以为了解决这个,添加了这个判断,这样就可以保证Goexit也会被recover住,这里是通过从runtime._panic中取出了程序计数器pc和栈指针sp并且调用runtime.recovery函数触发goroutine的调度,调度之前会准备好 sp、pc 以及函数的返回值。
第二部分主要是做panic的recover,这也与上面的流程基本差不多,他是从runtime._defer中取出了程序计数器pc和栈指针sp并调用recovery函数触发Goroutine,跳转到recovery函数是通过runtime.call进行的,我们看一下其源码(src/runtime/asm_amd.s 行):
因为go语言中的runtime环境是有自己的堆栈和goroutine,recovery函数也是在runtime环境执行的,所以要调度到m->g0来执行recovery函数,我们在看一下recovery函数:
在recovery 函数中,利用 g 中的两个状态码回溯栈指针 sp 并恢复程序计数器 pc 到调度器中,并调用 gogo 重新调度 g , goroutine 继续执行,recovery在调度过程中会将函数的返回值设置为1。这个有什么作用呢? 在deferproc函数中找到了答案:
当延迟函数中recover了一个panic时,就会返回1,当 runtime.deferproc 函数的返回值是 1 时,编译器生成的代码会直接跳转到调用方函数返回之前并执行 runtime.deferreturn,跳转到runtime.deferturn函数之后,程序就已经从panic恢复了正常的逻辑。
在这里runtime.fatalpanic实现了无法被恢复的程序崩溃,它在中止程序之前会通过 runtime.printpanics 打印出全部的 panic 消息以及调用时传入的参数。
这就是这个逻辑流程,累死我了。。。。
结尾给大家发一个小福利,哈哈,这个福利就是如果避免出现panic,要注意这些:这几个是比较典型的,还有很多会发生panic的地方,交给你们自行学习吧~。
好啦,这篇文章就到这里啦,素质三连(分享、点赞、在看)都是笔者持续创作更多优质内容的动力!
翻译:XDA论坛教程:如何手动编译TWRP Recovery
这是一个关于手动编译TWRP Recovery的教程,对于TWRP 3.x源代码开放后,你有机会根据自己的设备进行定制。但请注意,这需要一定的Linux基础和AOSP构建流程知识。
目前支持编译的版本包括Omni 6.0、7.1、8.1、9.0、CM .0、.1、.1以及LineageOS .0。推荐使用Omni 9.0,除非你的设备有超级分区。
如果你使用的是CM或LineageOS,TWRP需要放置在特定的文件夹(LineageOS/bootable/recovery-twrp)并设置RECOVERY_VARIANT。源代码可以在相关链接中找到,但请注意链接地址可能已更新。
编译时,建议使用轻量级构建清单,它适用于大多数情况,但可能需要额外的repo。在编译前,确保更改任何FLAGS(构建标志)会清除或执行'make clobber',以确保更改生效。
找到与你设备对应的BoardConfig.mk文件(通常在devices/制造商/代号文件夹),你需要配置相应的架构和平台设置,尤其是TW_THEME,它决定你的设备显示的主题。现在有五种主题选项,根据你的屏幕分辨率选择合适的。
除了分辨率,还有其他如RECOVERY_SDCARD_ON_DATA、BOARD_HAS_NO_REAL_SDCARD等标志,根据你的设备需求进行设置。例如,RECOVERY_SDCARD_ON_DATA可改变设备的文件存储方式。
关于fstab,TWRP 2.5及以上版本支持新特性,自动处理大多数分区。但如果是较旧版本,需要创建TWRP.fstab文件,以保持与其他恢复选项的兼容性。
在TWRP中,你可以为每个分区添加标志,如removable、storage、settingsstorage等,这些标志影响分区的行为和显示方式。例如,Galaxy S4的TWRP fstab示例显示了如何使用标志。
最后,如果你完成了编译并想让TWRP官方支持你的设备,你需要提供必要的信息,但请注意,我们不会为此提供奖励,但你可以通过XDA分享你的成果。此外,你还可以在Android模拟器上测试TWRP,这有利于开发和调试。
请在编译过程中遵循指南,如有任何问题,可以访问#twrp在Freenode上寻求帮助,或者在XDA论坛分享你的成功经验。
如何刷手机第三方中文TWRP的recovery
根据前几期我们了解到手机原来还有这么多新奇的东西!那么我们总说第三方recovery,那真正的第三方recovery长什么样子呢?它又有什么优点和缺点呢?怎么样才能刷入?
带着以上问题,让我们来到本期的讲解,著名的第三方Recovery——TWRP。
介绍TWRP之前,我们提一下CWM:
来源于网络
谷歌安卓系统刷机软件,英文全名为ClockworkMod Recovery,简称CWM。Android系统必备神器之一,可以非常方便地进行刷机。早期很多手机厂商未自己定制Recovery时便使用了CWM这种Recovery,大家可以参考我们之前发布的文章,自行学习。简单来说CWM进去之后就是很多行的英语,其中
Wipe data/factory reset
Wipe cache partition
Wipe Dalvik Cache
是CWM中比较常见的选项!
不能说CWM不好,起码它提供的功能比现有官方定制REC来说多很多。但同样官方有自己的想法和技术,久而久之就没多少人使用了。
接下来我们说说TWRP:
Team Win Recovery Project (TWRP):是一个 开放源码软件的定制恢复模式映像,供基于安卓的设备使用。它提供了一个支持触摸屏的界面,允许用户向第三方安装 固件和备份当前的系统。因此经常在root系统时安装,虽然它并不是root之后才能安装。
TWRP 让用户可以随时完整地备份他们的设备(包括 boot,system 等)用来恢复到任一状态,还可以使用内置的文件管理器来删除可能导致设备问题的文件,或添加一些文件来修复问题。
截至 年,TWRP 支持定制 ROM,内核,附件(例如 Google Apps,SuperSU,主题)和其他 MOD 的安装。
来源于网络
TWRP 也支持 擦除,备份,恢复和安装各种设备分区(例如 system,boot,userdata,缓存和内部存储)。 TWRP 还具有媒体传输协议,基本文件管理器,文件传输功能和终端。它也支持定制主题。
年 1 月,TWRP 团队发布了一个 Android 应用程序,该应用程序允许使用root 访问来刷入恢复; 然而,与恢复模式不同,该应用程序不是开源的。此应用程序还通过官方 TWRP 映像发送到已经或未经 root 的设备。 它默认安装为系统级别的应用程序,使其没有 root 权限无法在操作系统内移除。
来源于网络
而大家可以发现,官方的recovery就没有这么多的功能了。可为什么这么多recovery,偏偏就TWRP最著名呢?
因为很多第三方recovery都是基于TWRP定制的,改改代码和UI即可。有一个对MIUI支持比较好的第三方Recovery——橙狐rec,就是基于TWRP定制的。
所以大家应该知道了,第三方的REC功能有多么的强大,我们一定不要随意的解锁(这里指bl锁,不懂的请看之前我们科普的文章),导致手机不慎丢失或被盗走后,被他人刷入第三方REC,进而完成他人的目的!
来源于网络
网上有很多刷入TWRP的教程,感兴趣的可以去搜搜看,或者本篇文章点赞数过1k/收藏过,我们会单独出一期如何刷入TWRP的教程文章!
预告:
第一期:ROOT
第二期:面具——Magisk