英文:
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 <-ticker:
count++
conn, err := gorm.Open("postgres", param)
//conn, err := net.Dial("tcp", "127.0.0.1:5432")
if err != nil {
log.Warningf("try %v times... waiting for the postgres starting up...", 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论