Commit 248c3a3c authored by David Symonds's avatar David Symonds

regexp: avoid copying mutex in (*Regexp).Copy.

There's nothing guaranteeing that the *Regexp isn't in active use,
and so copying the sync.Mutex value is invalid.

Updates #14839.

Change-Id: Iddf52bf69df1b563377922399f64a571f76b95dd
Reviewed-on: https://go-review.googlesource.com/20841Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarAndrew Gerrand <adg@golang.org>
parent 815c9a7f
......@@ -81,6 +81,14 @@ var debug = false
// A Regexp is safe for concurrent use by multiple goroutines.
type Regexp struct {
// read-only after Compile
regexpRO
// cache of machines for running regexp
mu sync.Mutex
machine []*machine
}
type regexpRO struct {
expr string // as passed to Compile
prog *syntax.Prog // compiled program
onepass *onePassProg // onepass program or nil
......@@ -93,10 +101,6 @@ type Regexp struct {
numSubexp int
subexpNames []string
longest bool
// cache of machines for running regexp
mu sync.Mutex
machine []*machine
}
// String returns the source text used to compile the regular expression.
......@@ -109,10 +113,11 @@ func (re *Regexp) String() string {
// When using a Regexp in multiple goroutines, giving each goroutine
// its own copy helps to avoid lock contention.
func (re *Regexp) Copy() *Regexp {
r := *re
r.mu = sync.Mutex{}
r.machine = nil
return &r
// It is not safe to copy Regexp by value
// since it contains a sync.Mutex.
return &Regexp{
regexpRO: re.regexpRO,
}
}
// Compile parses a regular expression and returns, if successful,
......@@ -174,13 +179,15 @@ func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, error) {
return nil, err
}
regexp := &Regexp{
expr: expr,
prog: prog,
onepass: compileOnePass(prog),
numSubexp: maxCap,
subexpNames: capNames,
cond: prog.StartCond(),
longest: longest,
regexpRO: regexpRO{
expr: expr,
prog: prog,
onepass: compileOnePass(prog),
numSubexp: maxCap,
subexpNames: capNames,
cond: prog.StartCond(),
longest: longest,
},
}
if regexp.onepass == notOnePass {
regexp.prefix, regexp.prefixComplete = prog.Prefix()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment