当在lib/pq中进行观察时,只会发生错误。

huangapple go评论86阅读模式
英文:

an error only occur when observing in lib/pq

问题

我尝试使用gorm和pgsql调试一个Go服务器,当gorm尝试使用以下代码连接到pgsql时,它会出现panic错误:

d, err := gorm.Open("postgres", param)

根据堆栈信息,我发现问题出在lib/pq处理服务器版本的代码上:

case "server_version":
   var major1 int
   var major2 int
   var minor int

   // r.string是pgsql版本的字符串。
   // 我的版本是:12.4 (Debian 12.4-1.pgdg100+1)

   _, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor)
   if err == nil {
      cn.parameterStatus.serverVersion = major1*10000 + major2*100 + minor
   }

显然,字符串12.4 (Debian 12.4-1.pgdg100+1)与格式%d.%d.%d不匹配,因此出现错误。

但奇怪的是,只有在GoLand中进行调试时才会出现这个问题(不清楚vscode是否也会出现)。简单构建和运行时不会发生这种情况,输出结果如下:

[INFO] 2022-11-04 15:30:52 +0800 [start_postgres.go:103] detecting database connecting... pgdir=%v/yak/tmp_build/database
[INFO] 2022-11-04 15:30:52 +0800 [start_postgres.go:106] detected exsited database.
[INFO] 2022-11-04 15:30:52 +0800 [core.go:107] health info manager is loading
[INFO] 2022-11-04 15:30:52 +0800 [manager.go:70] health info: cache 60 infos
[INFO] 2022-11-04 15:30:52 +0800 [core.go:112] start to connection postgres
[INFO] 2022-11-04 15:30:52 +0800 [core.go:117] build basic database manager instance

这是完全正常的。然后我在lib/pq/conn.go的源代码中进行了一些修改:

rString := r.string()
fmt.Printf("\n%s\n\n", rString)
_, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor)
if err == nil {
   cn.parameterStatus.serverVersion = major1*10000 + major2*100 + minor
}

这里最奇怪的是,服务器崩溃并出现无限循环的错误日志:

[INFO] 2022-11-04 16:37:00 +0800 [start_postgres.go:103] detecting database connecting... pgdir=%v/yak/tmp_build/database

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:00 +0800 [start_postgres.go:110] open database failed: pq: invalid message format; expected string terminator
[INFO] 2022-11-04 16:37:00 +0800 [start_postgres.go:113] try to start a database...

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:02 +0800 [start_postgres.go:206] try pq: invalid message format; expected string terminator times... waiting for the postgres starting up...

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:03 +0800 [start_postgres.go:206] try pq: invalid message format; expected string terminator times... waiting for the postgres starting up...

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:04 +0800 [start_postgres.go:206] try pq: invalid message format; expected string terminator times... waiting for the postgres starting up...

...

我无法弄清楚为什么会发生这种情况,我不认为它是在goroutine中,因为主例程被阻塞,所以有人可以提供一些帮助吗?

依赖和IDE的版本:

GoLand v2022.2.4

go version go1.19.2 linux/amd64

gorm v1.9.2

github.com/lib/pq v1.1.0

postgresql v12.4 (Debian 12.4-1.pgdg100+1)

英文:

I tried to debug a go server with gorm & pgsql, an it exitted with panic when gorm try to connect to the pgsql with code:

d, err := gorm.Open("postgres", param)

and as I followed the stack, I found it is the problem with lib/pq proccess the server version:

case "server_version":
   var major1 int
   var major2 int
   var minor int

   //r.string is the string of pgsql version.
   //mine is: 12.4 (Debian 12.4-1.pgdg100+1)

   _, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor)
   if err == nil {
      cn.parameterStatus.serverVersion = major1*10000 + major2*100 + minor
   }

obivisouly, the string 12.4 (Debian 12.4-1.pgdg100+1) dosen't match format %d.%d.%d, so it exitted with error.

but the strange thing is, it will only exit when debugging in GoLand (don't know about vscode). It will not happen when simplely build & run, the output is:

[INFO] 2022-11-04 15:30:52 +0800 [start_postgres.go:103] detecting database connecting... pgdir=%v/yak/tmp_build/database
[INFO] 2022-11-04 15:30:52 +0800 [start_postgres.go:106] detected exsited database.
[INFO] 2022-11-04 15:30:52 +0800 [core.go:107] health info manager is loading
[INFO] 2022-11-04 15:30:52 +0800 [manager.go:70] health info: cache 60 infos
[INFO] 2022-11-04 15:30:52 +0800 [core.go:112] start to connection postgres
[INFO] 2022-11-04 15:30:52 +0800 [core.go:117] build basic database manager instance

which is absloutly normal. then I did some modify on the source code in lib/pq/conn.go

rString := r.string()
fmt.Printf("\n%s\n\n", rString)
_, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor)
if err == nil {
   cn.parameterStatus.serverVersion = major1*10000 + major2*100 + minor
}

and here is the strangest thing, the server crashed with infinite loop of error logging:

[INFO] 2022-11-04 16:37:00 +0800 [start_postgres.go:103] detecting database connecting... pgdir=%v/yak/tmp_build/database

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:00 +0800 [start_postgres.go:110] open database failed: pq: invalid message format; expected string terminator
[INFO] 2022-11-04 16:37:00 +0800 [start_postgres.go:113] try to start a database...

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:02 +0800 [start_postgres.go:206] try pq: invalid message format; expected string terminator times... waiting for the postgres starting up...

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:03 +0800 [start_postgres.go:206] try pq: invalid message format; expected string terminator times... waiting for the postgres starting up...

12.4 (Debian 12.4-1.pgdg100+1)

[WARN] 2022-11-04 16:37:04 +0800 [start_postgres.go:206] try pq: invalid message format; expected string terminator times... waiting for the postgres starting up...

...

I can't figure it out why would this happen, I don't think it's in a goroutine because the main routine is blocked, so is there anyone can offer some helps?

versions of dependencies and IDE:

GoLand v2022.2.4

go version go1.19.2 linux/amd64

gorm v1.9.2

github.com/lib/pq v1.1.0

postgresql v12.4 (Debian 12.4-1.pgdg100+1)

答案1

得分: 1

我已经弄清楚了关于错误的无限循环的问题,init连接后有一个select结构,代码如下:

select {
    case <-ticker:
        count++
        conn, err := gorm.Open("postgres", param)
        //conn, err := net.Dial("tcp", "127.0.0.1:5432")
        if err != nil {
            log.Warningf("尝试 %v 次...等待 postgres 启动...", err)
            continue
        }

        _ = conn.Close()
        return nil
}

所以问题是,当我打印r.string()时,它会返回一个错误。

在调试(GoLand)中会出现恐慌,但在构建和运行时正常工作。

英文:

I figured it out about the infinity loop of error, there's a select struct after the init connection, the code is:

select {
        case &lt;-ticker:
            count++
            conn, err := gorm.Open(&quot;postgres&quot;, param)
            //conn, err := net.Dial(&quot;tcp&quot;, &quot;127.0.0.1:5432&quot;)
            if err != nil {
                log.Warningf(&quot;try %v times... waiting for the postgres starting up...&quot;, err)
                continue
            }

            _ = conn.Close()
            return nil
        }

so the problem is, when I print r.string(), it will return an error.

also it will exitted with panic in debug (GoLand) but work normally when build and run.

huangapple
  • 本文由 发表于 2022年11月4日 17:34:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/74314852.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定