@@ -18,6 +18,7 @@ import (
1818 "context"
1919 "fmt"
2020 "runtime"
21+ "sync/atomic"
2122 "unicode/utf16"
2223
2324 "github.com/tetratelabs/wazero/api"
6364)
6465
6566// ShouldPanic determines whether the finalizer will panic if it finds a Regex that has not been closed.
66- var ShouldPanic bool = true
67+ var ShouldPanic = true
68+
69+ // RegexLeakHandler is a callback function that will be invoked if a finalizer is called for a Regex that has not
70+ // been closed. This allows applications to provide custom handling logic beyond panicing if a Regex leak is detected.
71+ var regexLeakHandler atomic.Value
72+
73+ // SetRegexLeakHandler sets a |handler| function to be executed if a finalizer is called for a Regex instance that
74+ // has not been properly closed through it's Close() method. Note that if a custom leak handler function is provided,
75+ // the ShouldPanic variable will be ignored and the code will not panic if a Regex leak is detected.
76+ func SetRegexLeakHandler (handler func ()) {
77+ regexLeakHandler .Store (handler )
78+ }
79+
80+ // getRegexLeakHandler returns the custom handler function set by SetRegexLeakHandler, or nil if no custom handler has
81+ // been set.
82+ func getRegexLeakHandler () func () {
83+ val := regexLeakHandler .Load ()
84+ if val == nil {
85+ return nil
86+ }
87+ return val .(func ())
88+ }
6789
6890// RegexFlags are flags to define the behavior of the regular expression. Use OR (|) to combine flags. All flag values
6991// were taken directly from ICU.
@@ -171,8 +193,13 @@ func CreateRegex(stringBufferInBytes uint32) Regex {
171193 // by GC, this finalizer ensures that regexes are being used as efficiently as possible by maximizing pool rotations.
172194 // Hopefully, this would be caught during development and not in production.
173195 runtime .SetFinalizer (pr , func (pr * privateRegex ) {
174- if pr .mod != nil && ShouldPanic {
175- panic ("Finalizer found a Regex that was never closed" )
196+ if pr .mod != nil {
197+ if leakHandler := getRegexLeakHandler (); leakHandler != nil {
198+ leakHandler ()
199+ } else if ShouldPanic {
200+ panic ("Finalizer found a Regex that was never closed" )
201+ }
202+ _ = pr .Close ()
176203 }
177204 })
178205 return pr
0 commit comments