Skip to content

sourcegraph/concではpanicを最後の1つしか拾えない

sourcegraph/concWaitGroup には WaitAndRecover メソッドが存在しているので、Wait の代わりにこれを使えば panic したときの値が取得できる。

var wg conc.WaitGroup
wg.Go(func() { panic("uoo") })
if p := wg.WaitAndRecover(); p != nil {
log.Fatalln(p.Value)
}

しかし複数の panic が発生した場合、最後に発生したものしか受け取れない。具体的には conc/panics 以下のコードで recover しているが、ここで複数保持していないことから分かる。

type Catcher struct {
recovered atomic.Pointer[Recovered]
}
func (p *Catcher) tryRecover() {
if val := recover(); val != nil {
rp := NewRecovered(1, val)
p.recovered.CompareAndSwap(nil, &rp)
}
}

なので、AWSクローラで実現しているような「panic のログを漏れなく出しつつ他のゴルーチンを止めない」ような挙動は素直に書けない。もともと自作のgo-recoveryをアーカイブしようと思っていて conc を調べたのだけど、go-recovery も有用なことが分かった。