Description
(From https://groups.google.com/forum/#!topic/golang-nuts/6nTWBLbAyKo)
When Parse() is called, a new lexer is created, and it will run in the background:
func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
[...]
t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
[...]
}
(https://github.com/golang/go/blob/master/src/text/template/parse/parse.go#L228)
This will start a go routine :
// lex creates a new scanner for the input string.
func lex(name, input, left, right string) *lexer {
if left == "" {
left = leftDelim
}
if right == "" {
right = rightDelim
}
l := &lexer{
name: name,
input: input,
leftDelim: left,
rightDelim: right,
items: make(chan item),
}
go l.run()
return l
}
(https://github.com/golang/go/blob/master/src/text/template/parse/lex.go#L191)
Now if the parser fails to parse, it will panic, and the error is recovered :
// recover is the handler that turns panics into returns from the top level of Parse.
func (t *Tree) recover(errp *error) {
e := recover()
if e != nil {
if _, ok := e.(runtime.Error); ok {
panic(e)
}
if t != nil {
t.stopParse()
}
*errp = e.(error)
}
return
}
(https://github.com/golang/go/blob/master/src/text/template/parse/parse.go#L191)
which will call t.stopParse():
// stopParse terminates parsing.
func (t *Tree) stopParse() {
t.lex = nil
t.vars = nil
t.funcs = nil
}
The lexer should be GC, except it's still running in the background, because no parser is there to pull on the channel.
I think the lex should have a abort() method to end the routine cleanly, otherwise each time the parser is called and failing, we leave a running lexer behind.
I will create a pull request to fix this, as I have already some code for that.
ps: Minux has confirmed the bug http://play.golang.org/p/qTQXuT3ktV