sqle icon indicating copy to clipboard operation
sqle copied to clipboard

BUG:扫描任务中,未正确处理函数返回值,导致Panic

Open winfredLIN opened this issue 7 months ago • 2 comments

版本信息(Version)

sqle:3.2404.0

问题描述(Describe)

问题1:

在sqle/server/auditplan/task.go中第500多行,有这样一段代码:

inst, _, err := dms.GetInstanceInProjectByName(ctx, string(at.ap.ProjectId), at.ap.InstanceName)

	if err != nil {
		at.logger.Warnf("get instance fail, error: %v", err)
		return
	}
	// This depends on: https://github.com/actiontech/sqle-oracle-plugin.
	// If your Oracle db plugin does not implement the parameter `service_name`,
	// you can only use the default service name `XE`.
	// TODO: using DB plugin to query SQL.
	serviceName := inst.AdditionalParams.GetParam("service_name").String()

其中 dms.GetInstanceInProjectByName方法的返回值是这样的:

func GetInstanceInProjectByName(ctx context.Context, projectUid, name string) (*model.Instance, bool, error)

返回值的第二个参数表示着是否拿到了数据源信息,若没有,则第一个返回参数是nil,在第一段代码中,并没有对这个返回参数进行处理,并且也没有判断instance是否为nil。 在以下场景会出现panic:用户创建了一个Oracle TopSQL扫描任务,用户删除了扫描任务的数据源,此时扫描任务再次运行到第一段代码时,inst变量为nil,err为nil,在inst.AdditionalParams.GetParam("service_name").String()时,由于inst为nil,发生panic。

小结一下这个问题:

  1. 方法调用没有正确处理返回值
  2. 方法本身对多返回值没有明确其含义,导致在开发的时候,不能第一时间得知返回值作用,需要进入该函数查看,增加开发成本
  3. 删除重要的资源对象前/后没有做校验或数据更新

问题2:

在用户提出这个问题时,还发生了一个衍生问题,请看日志:

截图或日志(Log)

在这一段日志中,Java报错,没有可以申请的存储空间了,看上去是内存不足,但实际上机器的内存是充足的,可能是JVM的可分配内存不足

2024-07-02T09:56:58.163+0800 [DEBUG] plugin: starting plugin: path=/usr/bin/sh args=[sh, -c, "java -jar plugins/sqle-oracle-plugin.jar"]
2024-07-02T09:56:58.164+0800 [DEBUG] plugin: plugin started: path=/usr/bin/sh pid=84439
2024-07-02T09:56:58.164+0800 [DEBUG] plugin: waiting for RPC address: path=/usr/bin/sh
2024-07-02T09:56:58.195+0800 [DEBUG] plugin.sh: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000003d1800000, 704643072, 0) failed; error='Cannot allocate memory' (errno=12)
2024-07-02T09:56:58.198+0800 [DEBUG] plugin: plugin process exited: path=/usr/bin/sh pid=84439 error="signal: killed"
2024-07-02T09:56:58.199+0800 [DEBUG] plugin.stdio: received EOF, stopping recv loop: err="rpc error: code = Unavailable desc = transport is closing"
[root@sqle etc]# free -h
              total        used        free      shared  buff/cache   available
Mem:            62G         17G         44G         11M        745M         44G
Swap:           31G          0B         31G
[root@sqle etc]#

关闭SQLE之后,查看了插件的进程,能够看到,插件的总启动数目到达了百的级别,实际上一个插件只会有一个进程,这里重复启动了大量插件,现象关联到上面报错的内存不足。

[root@sqle etc]# ps -ef | grep plugin | wc -l
260
[root@sqle etc]# ps -ef | grep plugins/sqle-oracle | wc -l
44

如何复现(To Reproduce)

~~问题1:创建了一个Oracle TopSQL扫描任务,删除了扫描任务的数据源,过一会或者直接重启SQLE,触发扫描任务,就会导致panic~~ 问题1:创建了一个Oracle TopSQL扫描任务,在数据库中硬删除某个数据源,过一会或者直接重启SQLE,触发扫描任务,就会导致panic 问题2:在panic的基础上,反复启动sqle(使用rpm安装,会自动重启sqle),就会创建大量的插件进程

修复时需要注意的点

需要排查一下相关dms.GetInstanceInProjectByName的用法是否有相同的问题

实现方案

  • 该问题的原因是因为直接调用返回值inst造成,调用方需要同时判断err,exist正常后,才能调用inst
  • 检查所有调用该方法的返回值使用是否正常
  • 删除实例时应该检查对应实例是否有正在执行的智能检查?
  • 增加方法注释

变更影响面

  • 获取流水线详情
  • 智能扫描-oracletopsql
  • 智能扫描-mysql_processlist
  • 智能扫描-库表元数据
  • 智能扫描-db2库表元数据
  • 智能扫描-db2_topsql
  • 智能扫描-dm_topsql
  • 智能扫描-ob_topsql
  • 智能扫描-oboracle_topsql
  • 智能扫描-pg库表元数据
  • 智能扫描-pgtopsql

受影响的模块或功能

  • 智能扫描

外部引用的潜在问题或风险

版本兼容性

测试建议

winfredLIN avatar Jul 09 '24 07:07 winfredLIN