Reputation: 947
I have some Golang code that is, very intermittently (once every few hours), resulting in a panic and I need some guidance understanding how to find the cause. The code is this (with line numbers):
audio-process.go:
var MyChannel chan<- interface{}
var newDatagramList = list.New()
func operateAudioProcessing() {
var channel = make(chan interface{})
MyChannel = channel
newDatagramList.Init()
...
415 go func() {
416 for cmd := range channel {
417 switch msg := cmd.(type) {
418 case *MyThing:
419 {
420 newDatagramList.PushBack(msg)
421 }
422 }
423 }
424 }()
425 }
...and the panic occurs when newDatagramList.PushBack()
is called at line 420. The code sending into this channel is:
audio-in.go:
thing := new(MyThing)
...
MyChannel <- thing
...and, to complete the picture, there is a separate timed go func()
which processes newDatagramList
as follows:
go func() {
var next *list.Element
for _ = range processTicker.C {
for newElement := newDatagramList.Front(); newElement != nil; newElement = next {
next = newElement.Next();
myProcessingFunction(newElement.Value.(*MyThing))
newDatagramList.Remove(newElement)
}
}
The panic output is:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x5702d1]
goroutine 12 [running]:
panic(0x76e520, 0xc82000e100)
/usr/lib/go-1.6/src/runtime/panic.go:481 +0x3e6
container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
/usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1
main.operateAudioProcessing.func2(0xc8200164e0, 0xc82000f310, 0xc820024078, 0x240)
/home/rob/gocode/src/audio-process.go:420 +0x58b
created by main.operateAudioProcessing
/home/rob/gocode/src/audio-process.go:442 +0x5ba
Which thing is the panic telling me is at fault here? There was no complaint about the allocation and send into the channel in the first place, so I don't see how that can be wrong. newDatagramList
is clearly initialised (and the channel has been running and receiving messages for some time).
How do I go about determining what's making me go bang?
Upvotes: 4
Views: 1491
Reputation: 55952
The panic stack:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x5702d1]
goroutine 12 [running]:
panic(0x76e520, 0xc82000e100)
/usr/lib/go-1.6/src/runtime/panic.go:481 +0x3e6
container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
/usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1
main.operateAudioProcessing.func2(0xc8200164e0, 0xc82000f310, 0xc820024078, 0x240)
/home/rob/gocode/src/audio-process.go:420 +0x58b
created by main.operateAudioProcessing
/home/rob/gocode/src/audio-process.go:442 +0x5ba
Is saying that an "invalid memory address or nil pointer dereference" is occurring at the top listed frame
container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
On
/usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1
Which looks to be from godoc
// PushBack inserts a new element e with value v at the back of list l and returns e.
func (l *List) PushBack(v interface{}) *Element {
l.lazyInit()
return l.insertValue(v, l.root.prev)
}
This is cool since it's in this frame it looks to be erroring on l.root.prev
The datatype that is being built on container/list
is completely unsynchronized and there are many interleaving of go routines that could result in an in-between state where list element pointers are being added removed at the same time.
For example remove
has many different operations:
func (l *List) remove(e *Element) *Element {
e.prev.next = e.next
e.next.prev = e.prev
e.next = nil // avoid memory leaks
e.prev = nil // avoid memory leaks
e.list = nil
l.len--
return e
}
If this was executed synchronously there wouldn't be an issue but because multiple go routines are operating on it.
Suppose we have an element E
, with a pointer to a previous and a next, and two goroutines acting on it
PREV - E - NEXT
GOROUTINE1 GOROUTINE2
READ - E.PREV returns element (E2) with `NEXT` -> E
REMOVE(E) is called
e.next = nil // avoid memory leaks
E2.NEXT.NEXT access occurs now Nil!!!
resulting in panic
Upvotes: 2