Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

signal SIGSEGV: segmentation violation #132

Closed
limpo1989 opened this issue May 16, 2023 · 2 comments
Closed

signal SIGSEGV: segmentation violation #132

limpo1989 opened this issue May 16, 2023 · 2 comments

Comments

@limpo1989
Copy link

使用gomonkey配合plugin,实现一个简单的热修复功能会发生崩溃,刚开始patching之后一切正常,运行一会以后就会发生错误

main.go

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"plugin"
	"reflect"
	"sync/atomic"
	"time"

	gomonkey "github.com/agiledragon/gomonkey/v2"
	"gocase/gopatch/route"
)

var HotfixVersion = "main"

func IndexHandler() func(http.ResponseWriter, *http.Request) {
	//return route.Index
	var counter int32
	return func(writer http.ResponseWriter, request *http.Request) {
		fmt.Fprintln(writer, "plugin handle:", atomic.AddInt32(&counter, 1))
	}
}

func main() {
	http.HandleFunc("/", route.Index)

	// 热修复 route.Index 逻辑
	{
		p, err := plugin.Open("http_v1.so")
		if nil != err {
			panic(err)
		}

		sym, err := p.Lookup("IndexHandler")
		if nil != err {
			panic(err)
		}

		fn := sym.(func() func(http.ResponseWriter, *http.Request))
		handler := fn()

		fmt.Println("patching...", reflect.ValueOf(route.Index).Pointer(), " => ", reflect.ValueOf(handler).Pointer())

		gomonkey.ApplyFunc(route.Index, handler)
	}

	// 等3s后开始启动客户端访问接口
	time.AfterFunc(time.Second*3, func() {

		fmt.Println("start client...")
		for i := 0; i < 3; i++ {
			go startClient()
		}
	})

	// 启动http服务器
	fmt.Println("http server listen...")
	err := http.ListenAndServe(":8080", nil)
	fmt.Println("http server listen failed: ", err)
}

func startClient() {
	for {
		resp, err := http.Get("http://127.0.0.1:8080/")
		if nil != err {
			fmt.Println("http.Get: ", err)
			return
		}
		io.Copy(os.Stdout, resp.Body)
		resp.Body.Close()
	}
}

route.go

var counter int32
func Index(writer http.ResponseWriter, request *http.Request) {
	fmt.Fprintln(writer, "main: hello gopatch/", atomic.AddInt32(&counter, 1))
}

run_http.sh

#!/bin/bash

set -e

echo "build main program..."
go build -gcflags=all=-l -ldflags="-X main.HotfixVersion=main" -o http_main main.go

echo "please modify v1 plugin, press enter key to continue..."
read input

echo "build plugin v1..."
go build -gcflags=all=-l -buildmode=plugin -ldflags="-X main.HotfixVersion=v1" -o http_v1.so main.go

echo "run main program..."
./http_main

输出结果

patching... 8606880  =>  139904623738208
http server listen...
start client...
plugin handle: 1
plugin handle: 3
plugin handle: 2
plugin handle: 4
plugin handle: 5
plugin handle: 6
plugin handle: 7
plugin handle: 9
plugin handle: 8
plugin handle: 10
plugin handle: 11
plugin handle: 13
plugin handle: 12
plugin handle: 14
plugin handle: 15
plugin handle: 16
plugin handle: 17
plugin handle: 18
plugin handle: 19
plugin handle: 20
plugin handle: 21
plugin handle: 22
plugin handle: 23
plugin handle: 25
plugin handle: 24
plugin handle: 26
plugin handle: 27
plugin handle: 29
plugin handle: 28
plugin handle: 31
plugin handle: 32
plugin handle: 33
plugin handle: 30
plugin handle: 34
plugin handle: 35
plugin handle: 36
plugin handle: 38
plugin handle: 37
plugin handle: 39
plugin handle: 41
unexpected fault address 0x8dffe8
fatal error: fault
plugin handle: 40
[signal SIGSEGV: segmentation violation code=0x2 addr=0x8dffe8 pc=0x8dffe8]

goroutine 179 [running]:
runtime.throw({0x8d9d5a?, 0xc000016000?})
        /usr/local/go/src/runtime/panic.go:1047 +0x5d fp=0xc000206a70 sp=0xc000206a40 pc=0x58e6dd
runtime.sigpanic()
        /usr/local/go/src/runtime/signal_unix.go:851 +0x1e5 fp=0xc000206aa0 sp=0xc000206a70 pc=0x5a5465
net/http.HandlerFunc.ServeHTTP(0x686a65?, {0x929960?, 0xc000344000?}, 0x922938?)
        /usr/local/go/src/net/http/server.go:2123 +0x2f fp=0xc000206ac8 sp=0xc000206aa0 pc=0x80444f
net/http.(*ServeMux).ServeHTTP(0x0?, {0x929960, 0xc000344000}, 0xc0001ce000)
        /usr/local/go/src/net/http/server.go:2500 +0xc2 fp=0xc000206b00 sp=0xc000206ac8 pc=0x8059a2
net/http.serverHandler.ServeHTTP({0xc00020b3b0?}, {0x929960?, 0xc000344000?}, 0xc0001ce000?)
        /usr/local/go/src/net/http/server.go:2936 +0x23c fp=0xc000206b98 sp=0xc000206b00 pc=0x806fdc
net/http.(*conn).serve(0xc000208f30, {0x929d68, 0xc00011af00})
        /usr/local/go/src/net/http/server.go:1995 +0xad0 fp=0xc000206fb8 sp=0xc000206b98 pc=0x8035b0
net/http.(*Server).Serve.func3()
        /usr/local/go/src/net/http/server.go:3089 +0x2e fp=0xc000206fe0 sp=0xc000206fb8 pc=0x80792e
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000206fe8 sp=0xc000206fe0 pc=0x5c2861
created by net/http.(*Server).Serve
        /usr/local/go/src/net/http/server.go:3089 +0x45f
...
@limpo1989
Copy link
Author

测试环境:

  • go version go1.20.4 linux/amd64
  • Ubuntu 20.04.5 LTS (WSL2)

@limpo1989
Copy link
Author

切换为 gohook 后运行正常了,不会崩溃了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant