Index: Include/pyerrors.h =================================================================== --- Include/pyerrors.h (revision 69200) +++ Include/pyerrors.h (working copy) @@ -323,6 +323,16 @@ PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) Py_GCC_ATTRIBUTE((format(printf, 3, 0))); +#if defined(_MSC_VER) && defined(_DEBUG) +PyAPI_FUNC(void) _Py_SetCRTErrorHandler(int enter); +#define Py_BEGIN_CRT_ERROR_HANDLING _Py_SetCRTErrorHandler(1); +#define Py_END_CRT_ERROR_HANDLING _Py_SetCRTErrorHandler(0); +#else +/* no-ops */ +#define Py_BEGIN_CRT_ERROR_HANDLING +#define Py_END_CRT_ERROR_HANDLING +#endif + #ifdef __cplusplus } #endif Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 69200) +++ Modules/posixmodule.c (working copy) @@ -581,9 +581,14 @@ fd = PyObject_AsFileDescriptor(fdobj); if (fd < 0) return NULL; + /* Wherever we accept integral file descriptors, we must use + * weaker error checking in the windows C runtime + */ + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS res = (*func)(fd); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING if (res < 0) return posix_error(); Py_INCREF(Py_None); @@ -6188,9 +6193,11 @@ int fd, res; if (!PyArg_ParseTuple(args, "i:close", &fd)) return NULL; + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS res = close(fd); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING if (res < 0) return posix_error(); Py_INCREF(Py_None); @@ -6208,10 +6215,12 @@ int fd_from, fd_to, i; if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to)) return NULL; + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS for (i = fd_from; i < fd_to; i++) close(i); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING Py_RETURN_NONE; } @@ -6226,9 +6235,11 @@ int fd; if (!PyArg_ParseTuple(args, "i:dup", &fd)) return NULL; + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS fd = dup(fd); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING if (fd < 0) return posix_error(); return PyInt_FromLong((long)fd); @@ -6245,9 +6256,11 @@ int fd, fd2, res; if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2)) return NULL; + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS res = dup2(fd, fd2); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING if (res < 0) return posix_error(); Py_INCREF(Py_None); @@ -6289,6 +6302,7 @@ if (PyErr_Occurred()) return NULL; + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS #if defined(MS_WIN64) || defined(MS_WINDOWS) res = _lseeki64(fd, pos, how); @@ -6296,6 +6310,7 @@ res = lseek(fd, pos, how); #endif Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING if (res < 0) return posix_error(); @@ -6325,9 +6340,11 @@ buffer = PyString_FromStringAndSize((char *)NULL, size); if (buffer == NULL) return NULL; + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS n = read(fd, PyString_AsString(buffer), size); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING if (n < 0) { Py_DECREF(buffer); return posix_error(); @@ -6351,9 +6368,12 @@ if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf)) return NULL; + /* turn off crt asserts on windows since we have no control over fd */ + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS size = write(fd, pbuf.buf, (size_t)pbuf.len); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING PyBuffer_Release(&pbuf); if (size < 0) return posix_error(); @@ -6377,9 +6397,11 @@ /* on OpenVMS we must ensure that all bytes are written to the file */ fsync(fd); #endif + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS res = FSTAT(fd, &st); Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING if (res != 0) { #ifdef MS_WINDOWS return win32_error("fstat", NULL); @@ -6419,6 +6441,7 @@ PyMem_FREE(mode); return NULL; } + Py_BEGIN_CRT_ERROR_HANDLING Py_BEGIN_ALLOW_THREADS #if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H) if (mode[0] == 'a') { @@ -6438,6 +6461,7 @@ fp = fdopen(fd, mode); #endif Py_END_ALLOW_THREADS + Py_END_CRT_ERROR_HANDLING PyMem_FREE(mode); if (fp == NULL) return posix_error(); @@ -6455,10 +6479,13 @@ static PyObject * posix_isatty(PyObject *self, PyObject *args) { - int fd; + int fd, atty; if (!PyArg_ParseTuple(args, "i:isatty", &fd)) return NULL; - return PyBool_FromLong(isatty(fd)); + Py_BEGIN_CRT_ERROR_HANDLING + atty = isatty(fd); + Py_END_CRT_ERROR_HANDLING + return PyBool_FromLong(atty); } #ifdef HAVE_PIPE Index: Objects/exceptions.c =================================================================== --- Objects/exceptions.c (revision 69200) +++ Objects/exceptions.c (working copy) @@ -1994,7 +1994,29 @@ } #endif +#if defined(_MSC_VER) && defined(_DEBUG) +#include +static _CRT_REPORT_HOOK prevCrtReportHook; +__declspec(thread) static int crt_report_hook_flag = 0; /* FALSE */ + +/* A function for temporarily disabling strict CRT error handling on + * windows. + * this is needed where we we have to accept a "raw" parameter from the + * user and have the CRT respond leniently, e.g. by issuing a EINVAL. + * Examples are functions that take integral file descriptors, + * strftime which takes an arbitrary format string, and the + * mode string for open() + */ +void _Py_SetCRTErrorHandler(int enter) { crt_report_hook_flag = enter; } + +int __cdecl +CrtReportHook(int reportType, char *message, int *returnValue) +{ + return crt_report_hook_flag; +} +#endif + PyMODINIT_FUNC _PyExc_Init(void) { @@ -2157,9 +2179,11 @@ #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) /* Set CRT argument error handler */ prevCrtHandler = _set_invalid_parameter_handler(InvalidParameterHandler); - /* turn off assertions in debug mode */ - prevCrtReportMode = _CrtSetReportMode(_CRT_ASSERT, 0); #endif +#if defined(_MSC_VER) && defined(_DEBUG) + /* turn off assertions between Py_(BEGIN|END)_CRT_ERROR_HANDLING */ + prevCrtReportHook = _CrtSetReportHook(CrtReportHook); +#endif } void @@ -2170,6 +2194,8 @@ #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) /* reset CRT error handling */ _set_invalid_parameter_handler(prevCrtHandler); - _CrtSetReportMode(_CRT_ASSERT, prevCrtReportMode); #endif +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtSetReportHook(prevCrtReportHook); +#endif }