Commit 95a91df0 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-30764: Windows support.SuppressCrashReport (#2423)

* Add Windows support to test.support.SuppressCrashReport: call
  SetErrorMode() and CrtSetReportMode().
* _testcapi: add CrtSetReportMode() and CrtSetReportFile() functions
  and CRT_xxx and CRTDBG_xxx constants needed by SuppressCrashReport.
parent 305f333a
......@@ -1863,8 +1863,34 @@ class SuppressCrashReport:
soft limit to 0.
"""
if sys.platform.startswith('win'):
# TODO: backport the Windows implementation
# see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx
# GetErrorMode is not available on Windows XP and Windows Server 2003,
# but SetErrorMode returns the previous value, so we can use that
import ctypes
self._k32 = ctypes.windll.kernel32
SEM_NOGPFAULTERRORBOX = 0x02
self.old_value = self._k32.SetErrorMode(SEM_NOGPFAULTERRORBOX)
self._k32.SetErrorMode(self.old_value | SEM_NOGPFAULTERRORBOX)
# Suppress assert dialogs in debug builds
# (see http://bugs.python.org/issue23314)
try:
import _testcapi
_testcapi.CrtSetReportMode
except (AttributeError, ImportError):
# no _testcapi or a release build
pass
else:
self.old_modes = {}
for report_type in [_testcapi.CRT_WARN,
_testcapi.CRT_ERROR,
_testcapi.CRT_ASSERT]:
old_mode = _testcapi.CrtSetReportMode(report_type,
_testcapi.CRTDBG_MODE_FILE)
old_file = _testcapi.CrtSetReportFile(report_type,
_testcapi.CRTDBG_FILE_STDERR)
self.old_modes[report_type] = old_mode, old_file
else:
try:
import resource
......@@ -1906,15 +1932,15 @@ class SuppressCrashReport:
return
if sys.platform.startswith('win'):
# TODO: backport the Windows implementation
pass
self._k32.SetErrorMode(self.old_value)
if self.old_modes:
import _testcapi
for report_type, (old_mode, old_file) in self.old_modes.items():
_testcapi.CrtSetReportMode(report_type, old_mode)
_testcapi.CrtSetReportFile(report_type, old_file)
else:
try:
import resource
except ImportError:
resource = None
if resource is not None:
try:
resource.setrlimit(resource.RLIMIT_CORE, self.old_value)
except (ValueError, OSError):
......
......@@ -11,6 +11,9 @@
#include "datetime.h"
#include "marshal.h"
#include <signal.h>
#ifdef MS_WINDOWS
# include <crtdbg.h>
#endif
#ifdef WITH_THREAD
#include "pythread.h"
......@@ -2501,6 +2504,42 @@ test_raise_signal(PyObject* self, PyObject *args)
}
#ifdef MS_WINDOWS
static PyObject*
msvcrt_CrtSetReportMode(PyObject* self, PyObject *args)
{
int type, mode;
int res;
if (!PyArg_ParseTuple(args, "ii:CrtSetReportMode", &type, &mode)) {
return NULL;
}
res = _CrtSetReportMode(type, mode);
if (res == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyInt_FromLong(res);
}
static PyObject*
msvcrt_CrtSetReportFile(PyObject* self, PyObject *args)
{
int type, file;
long res;
if (!PyArg_ParseTuple(args, "ii:CrtSetReportFile", &type, &file)) {
return NULL;
}
res = (long)_CrtSetReportFile(type, (_HFILE)file);
return PyInt_FromLong(res);
}
#endif
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
{"set_errno", set_errno, METH_VARARGS},
......@@ -2613,6 +2652,10 @@ static PyMethodDef TestMethods[] = {
{"pymarshal_read_object_from_file",
pymarshal_read_object_from_file, METH_VARARGS},
{"raise_signal", (PyCFunction)test_raise_signal, METH_VARARGS},
#ifdef MS_WINDOWS
{"CrtSetReportMode", (PyCFunction)msvcrt_CrtSetReportMode, METH_VARARGS},
{"CrtSetReportFile", (PyCFunction)msvcrt_CrtSetReportFile, METH_VARARGS},
#endif
{NULL, NULL} /* sentinel */
};
......@@ -2809,6 +2852,14 @@ init_testcapi(void)
PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyInt_FromSsize_t(PY_SSIZE_T_MIN));
PyModule_AddObject(m, "SIZEOF_PYGC_HEAD", PyInt_FromSsize_t(sizeof(PyGC_Head)));
#ifdef MS_WINDOWS
PyModule_AddIntConstant(m, "CRT_WARN", _CRT_WARN);
PyModule_AddIntConstant(m, "CRT_ERROR", _CRT_ERROR);
PyModule_AddIntConstant(m, "CRT_ASSERT", _CRT_ASSERT);
PyModule_AddIntConstant(m, "CRTDBG_MODE_FILE", _CRTDBG_MODE_FILE);
PyModule_AddIntConstant(m, "CRTDBG_FILE_STDERR", (int)_CRTDBG_FILE_STDERR);
#endif
TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
Py_INCREF(TestError);
PyModule_AddObject(m, "error", TestError);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment