gorhill / cronexpr

Cron expression parser in Go language (golang)
683 stars 168 forks source link

multi-goroutine map write when init first time #19

Open aiquestion opened 7 years ago

aiquestion commented 7 years ago
func makeLayoutRegexp(layout, value string) *regexp.Regexp {
    layout = strings.Replace(layout, `%value%`, value, -1)
    re := layoutRegexp[layout]
    if re == nil {
        re = regexp.MustCompile(layout)
        layoutRegexp[layout] = re
    }
    return re
}

This code will panic when multi-goroutine calls cronexp.Parse(xx) concurrently.

call stack:

fatal error: concurrent map writes

goroutine 33 [running]:
runtime.throw(0xdc8dbf, 0x15)
        /home/work/build_tmp/build/1480301702.549625122/xxxx/go/src/runtime/panic.go:566 +0x95 fp=0xc42005d920 sp=0xc42005d900
runtime.mapassign1(0xca0ae0, 0xc4201c72f0, 0xc42005da60, 0xc42005da58)
        /home/work/build_tmp/build/1480301702.549625122/xxxx/go/src/runtime/hashmap.go:458 +0x8ef fp=0xc42005da08 sp=0xc42005d920
github.com/gorhill/cronexpr.makeLayoutRegexp(0xdbeb61, 0x9, 0xdc5f55, 0x12, 0x0)
        /home/work/build_tmp/build/1480301702.549625122/xxxx/gopath/src/github.com/gorhill/cronexpr/cronexpr_parse.go:486 +0x141 fp=0xc42005da80 sp=0xc42005da08
github.com/gorhill/cronexpr.genericFieldParse(0xc420362c00, 0x1, 0xdbbdd6, 0x6, 0x0, 0x3b, 0x120ac80, 0x3c, 0x3c, 0xdc5f55, ...)
        /home/work/build_tmp/build/1480301702.549625122/xxxx/gopath/src/github.com/gorhill/cronexpr/cronexpr_parse.go:417 +0x22b fp=0xc42005db70 sp=0xc42005da80
github.com/gorhill/cronexpr.genericFieldHandler(0xc420362c00, 0x1, 0xdbbdd6, 0x6, 0x0, 0x3b, 0x120ac80, 0x3c, 0x3c, 0xdc5f55, ...)
        /home/work/build_tmp/build/1480301702.549625122/xxxx/gopath/src/github.com/gorhill/cronexpr/cronexpr_parse.go:268 +0x70 fp=0xc42005dcf8 sp=0xc42005db70
github.com/gorhill/cronexpr.(*Expression).secondFieldHandler(0xc4201380e0, 0xc420362c00, 0x1, 0xf, 0xc42149f3b0)
        /home/work/build_tmp/build/1480301702.549625122/xxxx/gopath/src/github.com/gorhill/cronexpr/cronexpr_parse.go:213 +0x6c fp=0xc42005dda0 sp=0xc42005dcf8
github.com/gorhill/cronexpr.Parse(0xc421315fa0, 0xe, 0x40f3bb, 0xc4202e9f78, 0x0)
        /home/work/build_tmp/build/1480301702.549625122/xxxx/gopath/src/github.com/gorhill/cronexpr/cronexpr.go:90 +0x16b fp=0xc42005de28 sp=0xc42005dda0

I will try to workaround this by call cronexp.Parse() when first start(no other goroutine init). :-) and maybe try to send a pull request.

s7v7nislands commented 7 years ago

will fix this?