mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
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/20841 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
parent
815c9a7f28
commit
248c3a3c7b
1 changed files with 22 additions and 15 deletions
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue