1 | # Tests that the stack size is big enough for the application. |
---|
2 | # |
---|
3 | # This file contains a collection of tests for one or more of the Tcl |
---|
4 | # built-in commands. Sourcing this file into Tcl runs the tests and |
---|
5 | # generates output for errors. No output means no errors were found. |
---|
6 | # |
---|
7 | # Copyright (c) 1998-2000 Ajuba Solutions. |
---|
8 | # |
---|
9 | # See the file "license.terms" for information on usage and redistribution |
---|
10 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
11 | # |
---|
12 | # RCS: @(#) $Id: stack.test,v 1.22 2007/12/13 15:26:07 dgp Exp $ |
---|
13 | |
---|
14 | if {[lsearch [namespace children] ::tcltest] == -1} { |
---|
15 | package require tcltest 2 |
---|
16 | namespace import -force ::tcltest::* |
---|
17 | } |
---|
18 | |
---|
19 | # Note that a failure in this test results in a crash of the executable. |
---|
20 | # In order to avoid that, we do a basic check of the current stacksize. |
---|
21 | # This size can be changed with ulimit (ksh/bash/sh) or limit (csh/tcsh). |
---|
22 | |
---|
23 | # This doesn't catch all cases, for example threads of lower stacksize |
---|
24 | # can still squeak through. A core check is really needed. -- JH |
---|
25 | |
---|
26 | testConstraint minStack2400 1 |
---|
27 | if {[testConstraint unix]} { |
---|
28 | set stackSize [exec /bin/sh -c "ulimit -s"] |
---|
29 | if {[string is integer $stackSize] && ($stackSize < 2400)} { |
---|
30 | puts stderr "WARNING: the default application stacksize of $stackSize\ |
---|
31 | may cause Tcl to\ncrash due to stack overflow before the\ |
---|
32 | recursion limit is reached.\nA minimum stacksize of 2400\ |
---|
33 | kbytes is recommended.\nSkipping infinite recursion test." |
---|
34 | testConstraint minStack2400 0 |
---|
35 | } |
---|
36 | } |
---|
37 | |
---|
38 | # |
---|
39 | # Custom match to detect a stack overflow independently of the mechanism that |
---|
40 | # triggered the error. |
---|
41 | # |
---|
42 | |
---|
43 | customMatch stackOverflow StackOverflow |
---|
44 | proc StackOverflow {- res} { |
---|
45 | set msgList [list \ |
---|
46 | "too many nested evaluations (infinite loop?)"\ |
---|
47 | "out of stack space (infinite loop?)"] |
---|
48 | expr {$res in $msgList} |
---|
49 | } |
---|
50 | |
---|
51 | test stack-1.1 {maxNestingDepth reached on infinite recursion} -constraints { |
---|
52 | minStack2400 |
---|
53 | } -body { |
---|
54 | # do this in a sub process in case it segfaults |
---|
55 | exec [interpreter] << { |
---|
56 | proc recurse {} { recurse } |
---|
57 | catch { recurse } rv |
---|
58 | puts $rv |
---|
59 | } |
---|
60 | } -match stackOverflow |
---|
61 | |
---|
62 | test stack-2.1 {maxNestingDepth reached on infinite recursion} -constraints { |
---|
63 | minStack2400 |
---|
64 | } -body { |
---|
65 | # do this in a sub process in case it segfaults |
---|
66 | exec [interpreter] << { |
---|
67 | interp alias {} unknown {} notaknownproc |
---|
68 | catch { unknown } msg |
---|
69 | puts $msg |
---|
70 | } |
---|
71 | } -match stackOverflow |
---|
72 | |
---|
73 | # Make sure that there is enough stack to run regexp even if we're |
---|
74 | # close to the recursion limit. [Bug 947070] [Patch 746378] |
---|
75 | test stack-3.1 {enough room for regexp near recursion limit} -body { |
---|
76 | # do this in a sub process in case it segfaults |
---|
77 | exec [interpreter] << { |
---|
78 | interp recursionlimit {} 10000 |
---|
79 | set depth 0 |
---|
80 | proc a { max } { |
---|
81 | if { [info level] < $max } { |
---|
82 | set ::depth [info level] |
---|
83 | a $max |
---|
84 | } else { |
---|
85 | regexp {^ ?} x |
---|
86 | } |
---|
87 | } |
---|
88 | catch { a 10001 } |
---|
89 | set depth2 $depth |
---|
90 | puts [list [a $depth] [expr { $depth2 - $depth }]] |
---|
91 | } |
---|
92 | } -result {1 1} |
---|
93 | |
---|
94 | # cleanup |
---|
95 | ::tcltest::cleanupTests |
---|
96 | return |
---|
97 | |
---|
98 | # Local Variables: |
---|
99 | # mode: tcl |
---|
100 | # End: |
---|