go-pcre
go-pcre copied to clipboard
CompileJIT is not threadsafe
pcrejit requires a separate thread specific stack. This leads to some very weird issues when using this library with multiple threads. I naively called CompileJIT in one part of the program and then used it in other parts without realizing that per thread stacks were required. This isn't featured in the documentation, nor is there a way to handle it in the current Go API.
http://www.pcre.org/original/doc/html/pcrejit.html#SEC9
http://www.pcre.org/original/doc/html/pcreapi.html#SEC8
https://stackoverflow.com/questions/28738674/is-the-pcre-library-thread-safe-if-not-which-do-you-recommend
package main
import (
"log"
pcre "github.com/gijsbers/go-pcre"
)
func findIndex(a pcre.Regexp) {
for {
// Compile a new function with JIT. Since this is running in a goroutine and
// probably a different thread the JIT stack will be violated.
b := pcre.MustCompileJIT("[^\\/><\\s]+", 0, 0)
if b.FindIndex([]byte(" <p>"), 0) == nil {
log.Fatal("b.FindIndex(...) should never equal nil")
}
if a.FindIndex([]byte(" <p>"), 0) == nil {
log.Fatal("a.FindIndex(...) should never equal nil")
}
}
}
func main() {
a := pcre.MustCompileJIT("[^\\/><\\s]+", 0, 0)
for i := 0; i < 4; i++ {
go findIndex(a)
}
findIndex(a)
}
FYI in the above example it fails with "a.FindIndex(...) should never equal nil"
Very well researched!
Likely using pcre JIT in go requires the use of LockOSThread, such that it is guaranteed that findIndex is executing on the same OS thread as MustCompileJIT.