Issue #11393: limit stack overflow test to 100 MB

Stop if the stack overflow doesn't occur after allocating 100 MB on the stack.
This commit is contained in:
Victor Stinner 2011-03-31 11:34:08 +02:00
parent 702624ecf7
commit f048075079
2 changed files with 37 additions and 8 deletions

View file

@ -69,7 +69,7 @@ class FaultHandlerTests(unittest.TestCase):
return output.splitlines() return output.splitlines()
def check_fatal_error(self, code, line_number, name_regex, def check_fatal_error(self, code, line_number, name_regex,
filename=None, all_threads=False): filename=None, all_threads=False, other_regex=None):
""" """
Check that the fault handler for fatal errors is enabled and check the Check that the fault handler for fatal errors is enabled and check the
traceback from the child process output. traceback from the child process output.
@ -90,6 +90,8 @@ class FaultHandlerTests(unittest.TestCase):
lineno=line_number, lineno=line_number,
name=name_regex, name=name_regex,
header=re.escape(header)) header=re.escape(header))
if other_regex:
regex += '|' + other_regex
output = self.get_output(code, False, filename) output = self.get_output(code, False, filename)
output = '\n'.join(output) output = '\n'.join(output)
self.assertRegex(output, regex) self.assertRegex(output, regex)
@ -153,7 +155,6 @@ faulthandler._fatal_error(b'xyz')
2, 2,
'xyz') 'xyz')
@unittest.skipIf(True, 'test disabled, see #11393')
@unittest.skipIf(not hasattr(faulthandler, '_stack_overflow'), @unittest.skipIf(not hasattr(faulthandler, '_stack_overflow'),
'need faulthandler._stack_overflow()') 'need faulthandler._stack_overflow()')
def test_stack_overflow(self): def test_stack_overflow(self):
@ -163,7 +164,8 @@ faulthandler.enable()
faulthandler._stack_overflow() faulthandler._stack_overflow()
""".strip(), """.strip(),
3, 3,
'(?:Segmentation fault|Bus error)') '(?:Segmentation fault|Bus error)',
other_regex='unable to raise a stack overflow')
def test_gil_released(self): def test_gil_released(self):
self.check_fatal_error(""" self.check_fatal_error("""

View file

@ -16,6 +16,9 @@
# define FAULTHANDLER_USER # define FAULTHANDLER_USER
#endif #endif
/* Allocate at maximum 100 MB of the stack to raise the stack overflow */
#define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
#define PUTS(fd, str) write(fd, str, strlen(str)) #define PUTS(fd, str) write(fd, str, strlen(str))
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
@ -742,15 +745,39 @@ faulthandler_fatal_error_py(PyObject *self, PyObject *args)
} }
#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION) #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
static PyObject * void*
faulthandler_stack_overflow(PyObject *self) stack_overflow(void *min_sp, void *max_sp, size_t *depth)
{ {
/* allocate 4096 bytes on the stack at each call */ /* allocate 4096 bytes on the stack at each call */
unsigned char buffer[4096]; unsigned char buffer[4096];
void *sp = &buffer;
*depth += 1;
if (sp < min_sp || max_sp < sp)
return sp;
buffer[0] = 1; buffer[0] = 1;
buffer[4095] = 2; buffer[4095] = 0;
faulthandler_stack_overflow(self); return stack_overflow(min_sp, max_sp, depth);
return PyLong_FromLong(buffer[0] + buffer[4095]); }
static PyObject *
faulthandler_stack_overflow(PyObject *self)
{
size_t depth, size;
void *sp = &depth, *stop;
depth = 0;
stop = stack_overflow(sp - STACK_OVERFLOW_MAX_SIZE,
sp + STACK_OVERFLOW_MAX_SIZE,
&depth);
if (sp < stop)
size = stop - sp;
else
size = sp - stop;
PyErr_Format(PyExc_RuntimeError,
"unable to raise a stack overflow (allocated %zu bytes "
"on the stack, %zu recursive calls)",
size, depth);
return NULL;
} }
#endif #endif