Message ID | CAOyqgcX981=u=Q0yCjZKP5vfiesRNVHnuWs0XYv7EAp+EXy8NQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
On Thu, Aug 4, 2016 at 6:48 PM, Ian Lance Taylor <iant@golang.org> wrote: > On Thu, Aug 4, 2016 at 1:11 AM, Uros Bizjak <ubizjak@gmail.com> wrote: >> On Thu, Aug 4, 2016 at 12:53 AM, Ian Lance Taylor <iant@golang.org> wrote: >>> On Thu, Jul 28, 2016 at 4:24 AM, Uros Bizjak <ubizjak@gmail.com> wrote: >>>> >>>> A new testsuite failure is introduced: >>>> >>>> FAIL: text/template >>>> >>>> on both, x86_64-linux-gnu and alpha-linux-gnu. >>>> >>>> The testcase corrupts stack with a too deep recursion. >>>> >>>> There is a part in libgo/go/text/template/exec.go that should handle >>>> this situaiton: >>>> >>>> // maxExecDepth specifies the maximum stack depth of templates within >>>> // templates. This limit is only practically reached by accidentally >>>> // recursive template invocations. This limit allows us to return >>>> // an error instead of triggering a stack overflow. >>>> const maxExecDepth = 100000 >>>> >>>> but the limit is either set too high, or the error handling code is >>>> inefficient on both, split-stack (x86_64) and non-split-stack (alpha) >>>> targets. Lowering this value to 10000 "fixes" the testcase on both >>>> targets. >>> >>> I can not recreate this problem on x86 or x86_64. >>> >>> Does this patch work around the problem on Alpha? >> >> Yes, the patch "fixes" the problem on alpha, but I still see the >> failure on x86_64, even with the unlimited stack. > > OK, I was able to recreate this by using GNU ld rather than gold. I > have committed the appended patch to reduce the number of recursive > template invocations, since you said that 10000 did let the test pass > for you, and it works for me using GNU ld. This number is still high > enough to not cut off any reasonable template execution. > > For this patch bootstrapped and ran Go testsuite on > x86_64-pc-linux-gnu, using both GNU ld and gold. Committed to > mainline. The fixed test now passes reliably on alpha, *but* fails sporadically on x86_64-linux-gnu with split-stack (GNU ld). This is what I get on x86_64 Fedora 24: $ while true; do LD_LIBRARY_PATH=../../.libs ./a.out; done Segmentation fault (core dumped) PASS Segmentation fault (core dumped) PASS Segmentation fault (core dumped) PASS PASS Segmentation fault (core dumped) PASS Segmentation fault (core dumped) PASS Segmentation fault (core dumped) PASS Segmentation fault (core dumped) Segmentation fault (core dumped) Segmentation fault (core dumped) Segmentation fault (core dumped) Segmentation fault (core dumped) PASS Segmentation fault (core dumped) PASS Segmentation fault (core dumped) Segmentation fault (core dumped) Segmentation fault (core dumped) PASS Segmentation fault (core dumped) PASS Segmentation fault (core dumped) Segmentation fault (core dumped) PASS PASS Segmentation fault (core dumped) PASS Segmentation fault (core dumped) Segmentation fault (core dumped) PASS Segmentation fault (core dumped) Segmentation fault (core dumped) Segmentation fault (core dumped) PASS Segmentation fault (core dumped) PASS ... Running the test under gdb, the segfault is at different places, but usually involves some insn that accesses the stack, e.g. mov %rdi,0x8(%rsp) push $0 call ... Uros.
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 239140) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -ca5b64137f013e3104fd74ee7d07ba556a501187 +235dffb0de1e99d6f521f052067f0e936bf63baa The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: libgo/go/text/template/exec.go =================================================================== --- libgo/go/text/template/exec.go (revision 238662) +++ libgo/go/text/template/exec.go (working copy) @@ -19,7 +19,9 @@ import ( // templates. This limit is only practically reached by accidentally // recursive template invocations. This limit allows us to return // an error instead of triggering a stack overflow. -const maxExecDepth = 100000 +// For gccgo we make this 10000 rather than 100000 to avoid stack overflow +// on non-split-stack systems. +const maxExecDepth = 10000 // state represents the state of an execution. It's not part of the // template so that multiple executions of the same template