升级go1.18版本json-iterator coredump问题

2023-11-01

unexpected fault address 0x0
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x80 addr=0x0 pc=0x46639f]

goroutine 26 [running]:
runtime.throw({0x10bae71?, 0x0?})
        /goroot/src/runtime/panic.go:992 +0x71 fp=0xc0002a70d0 sp=0xc0002a70a0 pc=0x436331
runtime.sigpanic()
        /goroot/src/runtime/signal_unix.go:825 +0x305 fp=0xc0002a7120 sp=0xc0002a70d0 pc=0x44c585
aeshashbody()
        /goroot/src/runtime/asm_amd64.s:1343 +0x39f fp=0xc0002a7128 sp=0xc0002a7120 pc=0x46639f
runtime.mapiternext(0xc00004e900)
        /goroot/src/runtime/map.go:934 +0x2cb fp=0xc0002a7198 sp=0xc0002a7128 pc=0x41022b
runtime.mapiterinit(0xc000280400?, 0xc0001f8f70?, 0x0?)
        /goroot/src/runtime/map.go:861 +0x228 fp=0xc0002a71b8 sp=0xc0002a7198 pc=0x40ff08
reflect.mapiterinit(0x40f81d?, 0xf094c0?, 0xc0001f8f78?)
        /goroot/src/runtime/map.go:1373 +0x19 fp=0xc0002a71e0 sp=0xc0002a71b8 pc=0x462c19
github.com/modern-go/reflect2.(*UnsafeMapType).UnsafeIterate(...)
        /gopath/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_map.go:112
github.com/json-iterator/go.(*sortKeysMapEncoder).Encode(0xc0005d0ae0, 0xc0001383d8, 0xc00028ca80)
        /gopath/pkg/mod/github.com/json-iterator/go@v1.1.10/reflect_map.go:291 +0x225 fp=0xc0002a7350 sp=0xc0002a71e0 pc=0x5e9045
github.com/json-iterator/go.(*onePtrEncoder).Encode(0xc00056d3a0, 0xc0005d0840, 0xc00004e900?)
        /gopath/pkg/mod/github.com/json-iterator/go@v1.1.10/reflect.go:219 +0x82 fp=0xc0002a7388 sp=0xc0002a7350 pc=0x5e1502
github.com/json-iterator/go.(*Stream).WriteVal(0xc00028ca80, {0xf29420, 0xc0005d0840})
        /gopath/pkg/mod/github.com/json-iterator/go@v1.1.10/reflect.go:98 +0x158 fp=0xc0002a73f8 sp=0xc0002a7388 pc=0x5e0818
github.com/json-iterator/go.(*frozenConfig).Marshal(0xc000150280, {0xf29420, 0xc0005d0840})
        /gopath/pkg/mod/github.com/json-iterator/go@v1.1.10/config.go:299 +0xc9 fp=0xc0002a7490 sp=0xc0002a73f8 pc=0x5d7ac9

今天用go1.18编译了之前的项目运行的时候core了,代码里面使用了recover捕获,然后用runtime.Stack打印了现场,看了下堆栈的信息发现是我们在使用json-iterator时出的问题,找到json-iterator的github
https://github.com/json-iterator/go/issues/608
解决方案已经有了,执行go get github.com/json-iterator/go@v1.1.12

看了下主要改动是json-iterator引用的reflect2包,增加了一个go_below_118.go文件一个go_above_118.go文件,主要区别是mapiterinit这个函数

//go_above_118.go
//go:noescape
//go:linkname mapiterinit reflect.mapiterinit
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer, it *hiter)

func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
	var it hiter
	mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj), &it)
	return &UnsafeMapIterator{
		hiter:      &it,
		pKeyRType:  type2.pKeyRType,
		pElemRType: type2.pElemRType,
	}
}
//go_below_118.go
//go:noescape
//go:linkname mapiterinit reflect.mapiterinit
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) (val *hiter)

func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
	return &UnsafeMapIterator{
		hiter:      mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)),
		pKeyRType:  type2.pKeyRType,
		pElemRType: type2.pElemRType,
	}
}

之所以这么改动原因是go1.18修改了mapiterinit接口,本来mapiterinit接口没有导出,奈何reflect2使用了骚操作go:linkname来引用非导出的接口,完美绕过了编译器,所以编译的时候虽然少了一个入参也没有报错,直到运行的时候才coredump

可以看下go1.18相较于go1.17的改动

go1.18
go1.17

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

升级go1.18版本json-iterator coredump问题 的相关文章