Closed defsky closed 5 years ago
从报错信息来看,是 timingwheel 库的 bug,我会尽快修复。
timingwheel 库现在已经支持 定时任务,所以我将自己临时修改的 timingwheel 库替换。 https://github.com/RussellLuo/timingwheel
老哥,你再测试看看。
我本地测试是没有问题的,你方便的话,发下你的测试脚本。
测试脚本就是这个项目里面的 example/pushmessage/main.go
还是这个报错,是不是不支持centos6.5呢? centos7里面跑就对的
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x804a6bc]
goroutine 1 [running]: runtime/internal/atomic.Xchg64(0x8d1778c, 0xcd350110, 0x16d, 0x0, 0x362) /usr/lib/golang/src/runtime/internal/atomic/asm_386.s:151 +0xc github.com/RussellLuo/timingwheel.(bucket).SetExpiration(...) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/bucket.go:74 github.com/RussellLuo/timingwheel.(TimingWheel).add(0x8c9a0a0, 0x8c99ea0, 0x8c9a0a0) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:79 +0x167 github.com/RussellLuo/timingwheel.(TimingWheel).add(0x8c9a000, 0x8c99ea0, 0x8c99ec0) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:106 +0x1f2 github.com/RussellLuo/timingwheel.(TimingWheel).addOrRun(0x8c9a000, 0x8c99ea0) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:113 +0x29 github.com/RussellLuo/timingwheel.(TimingWheel).ScheduleFunc(0x8c9a000, 0x817bd20, 0x8c14358, 0x8c102e8, 0x2) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:222 +0x2b5 github.com/defsky/gev.(Server).RunEvery(...) /home/gohome/pkg/mod/github.com/defsky/gev@v0.0.3/server.go:86 main.(*Server).Start(0x8c6a060) /home/repo/myserver/main.go:40 +0x136 main.main() /home/repo/myserver/main.go:97 +0x85 exit status 2
你把你的执行命令 和 回显 信息都贴上来我看看
这样? 这个main.go就是复制的 pushmessage/main.go [root@develop myserver]# go run main.go 2019/10/15 10:26:20 Starting server at :5555 panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x804a6bc]
goroutine 1 [running]: runtime/internal/atomic.Xchg64(0x9123e2c, 0xcd3cdcc8, 0x16d, 0x0, 0x17d) /usr/lib/golang/src/runtime/internal/atomic/asm_386.s:151 +0xc github.com/RussellLuo/timingwheel.(bucket).SetExpiration(...) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/bucket.go:74 github.com/RussellLuo/timingwheel.(TimingWheel).add(0x90ac0a0, 0x90abe80, 0x90ac0a0) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:79 +0x167 github.com/RussellLuo/timingwheel.(TimingWheel).add(0x90ac000, 0x90abe80, 0x90abea0) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:106 +0x1f2 github.com/RussellLuo/timingwheel.(TimingWheel).addOrRun(0x90ac000, 0x90abe80) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:113 +0x29 github.com/RussellLuo/timingwheel.(TimingWheel).ScheduleFunc(0x90ac000, 0x817bd20, 0x908a2b0, 0x90762d0, 0x2) /home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:222 +0x2b5 github.com/defsky/gev.(Server).RunEvery(...) /home/gohome/pkg/mod/github.com/defsky/gev@v0.0.3/server.go:86 main.(*Server).Start(0x909a030) /home/repo/myserver/main.go:40 +0x136 main.main() /home/repo/myserver/main.go:97 +0x85 exit status 2
你把 main.go 也贴出来把
package main
import ( "container/list" "github.com/defsky/gev" "github.com/Allenxuxu/gev/connection" "github.com/Allenxuxu/ringbuffer" "log" "sync" "time" )
type Server struct { ip string port string conn list.List mu sync.RWMutex server gev.Server }
func New(ip, port string) (*Server, error) { var err error s := new(Server) s.conn = list.New() s.server, err = gev.NewServer(s, gev.Address(ip+":"+port)) if err != nil { return nil, err }
s.ip = ip
s.port = port
return s, nil
}
func (s *Server) Start() { log.Printf("Starting server at %s:%s\n", s.ip, s.port)
s.server.RunEvery(1*time.Second, s.RunPush)
s.server.Start()
}
func (s *Server) Stop() { s.server.Stop() }
func (s Server) RunPush() { var next list.Element
s.mu.RLock()
defer s.mu.RUnlock()
for e := s.conn.Front(); e != nil; e = next {
next = e.Next()
c := e.Value.(*connection.Connection)
_ = c.Send([]byte("hello\n"))
}
}
func (s Server) OnConnect(c connection.Connection) { log.Println(" OnConnect : ", c.PeerAddr())
s.mu.Lock()
e := s.conn.PushBack(c)
s.mu.Unlock()
c.SetContext(e)
} func (s Server) OnMessage(c connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte) { log.Println("OnMessage") first, end := buffer.PeekAll() out = first if len(end) > 0 { out = append(out, end...) } buffer.RetrieveAll() return }
func (s Server) OnClose(c connection.Connection) { log.Println("OnClose") e := c.Context().(*list.Element)
s.mu.Lock()
s.conn.Remove(e)
s.mu.Unlock()
}
func main() { s, err := New("", "5555") if err != nil { panic(err) } defer s.Stop()
s.Start()
}
package main
import (
"container/list"
"github.com/Allenxuxu/gev"
"github.com/Allenxuxu/gev/connection"
"github.com/Allenxuxu/ringbuffer"
"log"
"sync"
"time"
)
type Server struct {
ip string
port string
conn *list.List
mu sync.RWMutex
server *gev.Server
}
func New(ip, port string) (*Server, error) {
var err error
s := new(Server)
s.conn = list.New()
s.server, err = gev.NewServer(s,
gev.Address(ip+":"+port))
if err != nil {
return nil, err
}
s.ip = ip
s.port = port
return s, nil
}
func (s *Server) Start() {
log.Printf("Starting server at %s:%s\n", s.ip, s.port)
s.server.RunEvery(1*time.Second, s.RunPush)
s.server.Start()
}
func (s *Server) Stop() {
s.server.Stop()
}
func (s *Server) RunPush() {
var next *list.Element
s.mu.RLock()
defer s.mu.RUnlock()
for e := s.conn.Front(); e != nil; e = next {
next = e.Next()
c := e.Value.(*connection.Connection)
_ = c.Send([]byte("hello\n"))
}
}
func (s *Server) OnConnect(c *connection.Connection) {
log.Println(" OnConnect : ", c.PeerAddr())
s.mu.Lock()
e := s.conn.PushBack(c)
s.mu.Unlock()
c.SetContext(e)
}
func (s *Server) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte) {
log.Println("OnMessage")
first, end := buffer.PeekAll()
out = first
if len(end) > 0 {
out = append(out, end...)
}
buffer.RetrieveAll()
return
}
func (s *Server) OnClose(c *connection.Connection) {
log.Println("OnClose")
e := c.Context().(*list.Element)
s.mu.Lock()
s.conn.Remove(e)
s.mu.Unlock()
}
func main() {
s, err := New("", "5555")
if err != nil {
panic(err)
}
defer s.Stop()
s.Start()
}
go run main.go
2019/10/15 10:49:28 Starting server at :5555
2019/10/15 10:49:50 OnConnect : 127.0.0.1:63521
2019/10/15 10:49:55 OnClose
我这样启动没问题,区别就在于 导入包 "github.com/defsky/gev" 。
你复制我这个代码,再试试。
ps:建议学一下 markdown 的语法,这样贴代码比较容易阅读。
就算直接运行 gev/example/pushmessage/main.go,都是这样的
[root@develop pushmessage]# echo $GOPATH
/home/gohome
[root@develop pushmessage]# pwd
/home/gohome/src/gev/example/pushmessage
[root@develop pushmessage]# go run main.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x804a6bc]
goroutine 1 [running]:
runtime/internal/atomic.Xchg64(0x9108e4c, 0xcd623748, 0x16d, 0x0, 0x33d)
/usr/lib/golang/src/runtime/internal/atomic/asm_386.s:151 +0xc
github.com/RussellLuo/timingwheel.(*bucket).SetExpiration(...)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/bucket.go:74
github.com/RussellLuo/timingwheel.(*TimingWheel).add(0x909a0a0, 0x9099ea0, 0x909a0a0)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:79 +0x167
github.com/RussellLuo/timingwheel.(*TimingWheel).add(0x909a000, 0x9099ea0, 0x9099ec0)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:106 +0x1f2
github.com/RussellLuo/timingwheel.(*TimingWheel).addOrRun(0x909a000, 0x9099ea0)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:113 +0x29
github.com/RussellLuo/timingwheel.(*TimingWheel).ScheduleFunc(0x909a000, 0x817bbb0, 0x9014320, 0x90102d8, 0x806ff75)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:222 +0x2b5
github.com/Allenxuxu/gev.(*Server).RunEvery(...)
/home/gohome/src/gev/server.go:86
main.(*Server).Start(0x90503c0)
/home/gohome/src/gev/example/pushmessage/main.go:36 +0x97
main.main()
/home/gohome/src/gev/example/pushmessage/main.go:99 +0x85
exit status 2
你的 go 版本和环境发下,我看看能不能复现。
这个?
[root@develop pushmessage]# uname -a
Linux develop 2.6.32-358.el6.i686 #1 SMP Thu Feb 21 21:50:49 UTC 2013 i686 i686 i386 GNU/Linux
[root@develop pushmessage]# go version
go version go1.13 linux/386
[root@develop pushmessage]# go env
GO111MODULE="on"
GOARCH="386"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="386"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/gohome"
GOPRIVATE=""
GOPROXY="https://goproxy.io"
GOROOT="/usr/lib/golang"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_386"
GCCGO="gccgo"
GO386="sse2"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/gohome/src/gev/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m32 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build136523118=/tmp/go-build"
[root@develop pushmessage]#
我这边没你这个机器的环境,我看日志觉得还是 timingwheel 库 的问题。
你先试试运行下面这个,会不会 panic :
package main
import (
"fmt"
"time"
"github.com/RussellLuo/timingwheel"
)
type EveryScheduler struct {
Interval time.Duration
}
func (s *EveryScheduler) Next(prev time.Time) time.Time {
return prev.Add(s.Interval)
}
func main() {
tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
tw.Start()
defer tw.Stop()
_ = tw.ScheduleFunc(&EveryScheduler{time.Second}, func() {
fmt.Println("The timer fires")
})
select {}
}
我这边没你这个机器的环境,我看日志觉得还是 timingwheel 库 的问题。
你先试试运行下面这个,会不会 panic :
package main import ( "fmt" "time" "github.com/RussellLuo/timingwheel" ) type EveryScheduler struct { Interval time.Duration } func (s *EveryScheduler) Next(prev time.Time) time.Time { return prev.Add(s.Interval) } func main() { tw := timingwheel.NewTimingWheel(time.Millisecond, 20) tw.Start() defer tw.Stop() _ = tw.ScheduleFunc(&EveryScheduler{time.Second}, func() { fmt.Println("The timer fires") }) select {} }
这个也会panic
[root@develop test]# go run main.go
go: finding github.com/RussellLuo/timingwheel latest
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x8049fac]
goroutine 1 [running]:
runtime/internal/atomic.Xchg64(0x9c66bcc, 0xcdfcee50, 0x16d, 0x0, 0x1)
/usr/lib/golang/src/runtime/internal/atomic/asm_386.s:151 +0xc
github.com/RussellLuo/timingwheel.(*bucket).SetExpiration(...)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/bucket.go:74
github.com/RussellLuo/timingwheel.(*TimingWheel).add(0x9c761e0, 0x9c66620, 0x9c761e0)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:79 +0x167
github.com/RussellLuo/timingwheel.(*TimingWheel).add(0x9c76140, 0x9c66620, 0x9c76140)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:106 +0x1f2
github.com/RussellLuo/timingwheel.(*TimingWheel).add(0x9c760a0, 0x9c66620, 0x9c66640)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:106 +0x1f2
github.com/RussellLuo/timingwheel.(*TimingWheel).addOrRun(0x9c760a0, 0x9c66620)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:113 +0x29
github.com/RussellLuo/timingwheel.(*TimingWheel).ScheduleFunc(0x9c760a0, 0x81173c0, 0x9c120b8, 0x8105430, 0x9c760a0)
/home/gohome/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20190930141959-b40c04085073/timingwheel.go:222 +0x2b5
main.main()
/home/repo/test/main.go:23 +0xba
exit status 2
是的, bug 就在这里 timingwheel 库里。 但是我在 centos7 的机器上是没问题的,你是只有 centos6.5 的机器会有问题吗?
是的, bug 就在这里 timingwheel 库里。 但是我在 centos7 的机器上是没问题的,你是只有 centos6.5 的机器会有问题吗?
是的,centos 7正常,centos 6.5会有这个panic
https://github.com/RussellLuo/timingwheel/issues/13
我晚上也会再配个环境,找找问题。
老哥,可以帮忙再测测吗?
下面的代码,再运行看看,看看会不会 panic :
ps:和之前的代码,导入的包地址不通。
package main
import (
"fmt"
"time"
"github.com/Allenxuxu/timingwheel"
)
type EveryScheduler struct {
Interval time.Duration
}
func (s *EveryScheduler) Next(prev time.Time) time.Time {
return prev.Add(s.Interval)
}
func main() {
tw := timingwheel.NewTimingWheel(time.Millisecond, 20)
tw.Start()
defer tw.Stop()
_ = tw.ScheduleFunc(&EveryScheduler{time.Second}, func() {
fmt.Println("The timer fires")
})
select {}
}
好了。
[root@develop test]# go run main.go
go: finding github.com/Allenxuxu/timingwheel latest
go: downloading github.com/Allenxuxu/timingwheel v0.0.0-20191015090400-4a0bc1c55c54
go: extracting github.com/Allenxuxu/timingwheel v0.0.0-20191015090400-4a0bc1c55c54
The timer fires
The timer fires
The timer fires
The timer fires
The timer fires
The timer fires
The timer fires
The timer fires
The timer fires
The timer fires
^Csignal: interrupt
[root@develop test]#
...
TEXT runtime∕internal∕atomic·Xchg64(SB),NOSPLIT,$0-20
--
| // no XCHGQ so use CMPXCHG8B loop
| MOVL ptr+0(FP), BP
| TESTL $7, BP
| JZ 2(PC)
| MOVL 0, AX // crash when unaligned
...
上面最后一行,注释说明了,未对齐会崩溃。 你是32 位机器,可能内存未对齐,导致了崩溃。 我 fork了 timingwheel 仓库,调整了字段位置,使内存对齐了 :https://github.com/Allenxuxu/timingwheel/commit/4a0bc1c55c54da30bcb68d6986315c7a0e08c312
我已经给 RussellLuo/timingwheel PR 了 :https://github.com/RussellLuo/timingwheel/pull/14
好的 谢谢! 等你更新了gev库后 我就可以正常用了吗?
我已经提交了代码了:将 RussellLuo/timingwheel 替换成 Allenxuxu/timingwheel 了。
RussellLuo 合并我的代码后,我再切回来,现在你可以正常使用。
感谢帮忙测试🙏
RussellLuo 已经合并我的代码,已经切回将 RussellLuo/timingwheel ,可以拉取最新 gev 代码获取。
RussellLuo 已经合并我的代码,已经切回将 RussellLuo/timingwheel ,可以拉取最新 gev 代码获取。
go get 获取到的怎么总是v0.0.2这个版本 是不是还需要发给release才能获取到最新版本呢?
已经发布 release v0.1.0 https://github.com/Allenxuxu/gev/releases/tag/v0.1.0
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x804a6bc]
goroutine 1 [running]: runtime/internal/atomic.Xchg64(0xa1201ac, 0xc9fda7b8, 0x16d, 0x0, 0x38b) /usr/lib/golang/src/runtime/internal/atomic/asm_386.s:151 +0xc github.com/Allenxuxu/timingwheel%2eV2.(bucket).SetExpiration(...) /home/gohome/pkg/mod/github.com/!allenxuxu/timingwheel.!v2@v0.0.0-20190920124930-519aff1ed880/bucket.go:74 github.com/Allenxuxu/timingwheel%2eV2.(TimingWheel).add(0xa0ae0a0, 0xa0ade80, 0xa0ae0a0) /home/gohome/pkg/mod/github.com/!allenxuxu/timingwheel.!v2@v0.0.0-20190920124930-519aff1ed880/timingwheel.go:79 +0x167 github.com/Allenxuxu/timingwheel%2eV2.(TimingWheel).add(0xa0ae000, 0xa0ade80, 0xa0adea0) /home/gohome/pkg/mod/github.com/!allenxuxu/timingwheel.!v2@v0.0.0-20190920124930-519aff1ed880/timingwheel.go:106 +0x1f2 github.com/Allenxuxu/timingwheel%2eV2.(TimingWheel).addOrRun(0xa0ae000, 0xa0ade80) /home/gohome/pkg/mod/github.com/!allenxuxu/timingwheel.!v2@v0.0.0-20190920124930-519aff1ed880/timingwheel.go:113 +0x29 github.com/Allenxuxu/timingwheel%2eV2.(TimingWheel).EveryFunc(0xa0ae000, 0x3b9aca00, 0x0, 0xa0782c0, 0xa07c3a0) /home/gohome/pkg/mod/github.com/!allenxuxu/timingwheel.!v2@v0.0.0-20190920124930-519aff1ed880/timingwheel.go:185 +0x190 github.com/Allenxuxu/gev.(Server).RunEvery(...) /home/gohome/pkg/mod/github.com/!allenxuxu/gev@v0.0.2/server.go:84 main.(*Server).Start(0xa07c3a0) /home/gohome/pkg/mod/github.com/!allenxuxu/gev@v0.0.2/example/pushmessage/main.go:33 +0x72 main.main() /home/gohome/pkg/mod/github.com/!allenxuxu/gev@v0.0.2/example/pushmessage/main.go:90 +0x85 exit status 2
系统信息: Linux develop 2.6.32-358.el6.i686 #1 SMP Thu Feb 21 21:50:49 UTC 2013 i686 i686 i386 GNU/Linux