Issue #23524: Replace _PyVerify_fd function with calling _set_thread_local_invalid_parameter_handler on every thread.
This commit is contained in:
parent
eef20de744
commit
d81431f587
|
@ -32,17 +32,6 @@ PyAPI_DATA(int) Py_HasFileSystemDefaultEncoding;
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
PyAPI_FUNC(PyObject *) PyFile_NewStdPrinter(int);
|
PyAPI_FUNC(PyObject *) PyFile_NewStdPrinter(int);
|
||||||
PyAPI_DATA(PyTypeObject) PyStdPrinter_Type;
|
PyAPI_DATA(PyTypeObject) PyStdPrinter_Type;
|
||||||
|
|
||||||
#if defined _MSC_VER && _MSC_VER >= 1400
|
|
||||||
/* A routine to check if a file descriptor is valid on Windows. Returns 0
|
|
||||||
* and sets errno to EBADF if it isn't. This is to avoid Assertions
|
|
||||||
* from various functions in the Windows CRT beginning with
|
|
||||||
* Visual Studio 2005
|
|
||||||
*/
|
|
||||||
int _PyVerify_fd(int fd);
|
|
||||||
#else
|
|
||||||
#define _PyVerify_fd(A) (1) /* dummy */
|
|
||||||
#endif
|
|
||||||
#endif /* Py_LIMITED_API */
|
#endif /* Py_LIMITED_API */
|
||||||
|
|
||||||
/* A routine to check if a file descriptor can be select()-ed. */
|
/* A routine to check if a file descriptor can be select()-ed. */
|
||||||
|
|
|
@ -108,6 +108,18 @@ PyAPI_FUNC(int) _Py_get_blocking(int fd);
|
||||||
PyAPI_FUNC(int) _Py_set_blocking(int fd, int blocking);
|
PyAPI_FUNC(int) _Py_set_blocking(int fd, int blocking);
|
||||||
#endif /* !MS_WINDOWS */
|
#endif /* !MS_WINDOWS */
|
||||||
|
|
||||||
|
#if defined _MSC_VER && _MSC_VER >= 1400
|
||||||
|
/* A routine to check if a file descriptor is valid on Windows. Returns 0
|
||||||
|
* and sets errno to EBADF if it isn't. This is to avoid Assertions
|
||||||
|
* from various functions in the Windows CRT beginning with
|
||||||
|
* Visual Studio 2005
|
||||||
|
*/
|
||||||
|
int _PyVerify_fd(int fd);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define _PyVerify_fd(A) (1) /* dummy */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* Py_LIMITED_API */
|
#endif /* Py_LIMITED_API */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -182,7 +182,7 @@ check_fd(int fd)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_FSTAT) || defined(MS_WINDOWS)
|
#if defined(HAVE_FSTAT) || defined(MS_WINDOWS)
|
||||||
struct _Py_stat_struct buf;
|
struct _Py_stat_struct buf;
|
||||||
if (!_PyVerify_fd(fd) || (_Py_fstat(fd, &buf) < 0 && errno == EBADF)) {
|
if (_Py_fstat(fd, &buf) < 0 && errno == EBADF) {
|
||||||
PyObject *exc;
|
PyObject *exc;
|
||||||
char *msg = strerror(EBADF);
|
char *msg = strerror(EBADF);
|
||||||
exc = PyObject_CallFunction(PyExc_OSError, "(is)",
|
exc = PyObject_CallFunction(PyExc_OSError, "(is)",
|
||||||
|
|
|
@ -1051,99 +1051,16 @@ PyLong_FromPy_off_t(Py_off_t offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined _MSC_VER && _MSC_VER >= 1400
|
#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900
|
||||||
/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
|
/* Legacy implementation of _PyVerify_fd_dup2 while transitioning to
|
||||||
* valid and raise an assertion if it isn't.
|
* MSVC 14.0. This should eventually be removed. (issue23524)
|
||||||
* Normally, an invalid fd is likely to be a C program error and therefore
|
|
||||||
* an assertion can be useful, but it does contradict the POSIX standard
|
|
||||||
* which for write(2) states:
|
|
||||||
* "Otherwise, -1 shall be returned and errno set to indicate the error."
|
|
||||||
* "[EBADF] The fildes argument is not a valid file descriptor open for
|
|
||||||
* writing."
|
|
||||||
* Furthermore, python allows the user to enter any old integer
|
|
||||||
* as a fd and should merely raise a python exception on error.
|
|
||||||
* The Microsoft CRT doesn't provide an official way to check for the
|
|
||||||
* validity of a file descriptor, but we can emulate its internal behaviour
|
|
||||||
* by using the exported __pinfo data member and knowledge of the
|
|
||||||
* internal structures involved.
|
|
||||||
* The structures below must be updated for each version of visual studio
|
|
||||||
* according to the file internal.h in the CRT source, until MS comes
|
|
||||||
* up with a less hacky way to do this.
|
|
||||||
* (all of this is to avoid globally modifying the CRT behaviour using
|
|
||||||
* _set_invalid_parameter_handler() and _CrtSetReportMode())
|
|
||||||
*/
|
*/
|
||||||
/* The actual size of the structure is determined at runtime.
|
|
||||||
* Only the first items must be present.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1900
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
intptr_t osfhnd;
|
|
||||||
__int64 startpos;
|
|
||||||
char osfile;
|
|
||||||
} my_ioinfo;
|
|
||||||
|
|
||||||
#define IOINFO_L2E 6
|
|
||||||
#define IOINFO_ARRAYS 128
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
intptr_t osfhnd;
|
|
||||||
char osfile;
|
|
||||||
} my_ioinfo;
|
|
||||||
|
|
||||||
#define IOINFO_L2E 5
|
#define IOINFO_L2E 5
|
||||||
#define IOINFO_ARRAYS 64
|
#define IOINFO_ARRAYS 64
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern __declspec(dllimport) char * __pioinfo[];
|
|
||||||
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
|
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
|
||||||
#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
|
#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
|
||||||
#define FOPEN 0x01
|
|
||||||
#define _NO_CONSOLE_FILENO (intptr_t)-2
|
#define _NO_CONSOLE_FILENO (intptr_t)-2
|
||||||
|
|
||||||
/* This function emulates what the windows CRT does to validate file handles */
|
|
||||||
int
|
|
||||||
_PyVerify_fd(int fd)
|
|
||||||
{
|
|
||||||
const int i1 = fd >> IOINFO_L2E;
|
|
||||||
const int i2 = fd & ((1 << IOINFO_L2E) - 1);
|
|
||||||
|
|
||||||
static size_t sizeof_ioinfo = 0;
|
|
||||||
|
|
||||||
/* Determine the actual size of the ioinfo structure,
|
|
||||||
* as used by the CRT loaded in memory
|
|
||||||
*/
|
|
||||||
if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
|
|
||||||
sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
|
|
||||||
}
|
|
||||||
if (sizeof_ioinfo == 0) {
|
|
||||||
/* This should not happen... */
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See that it isn't a special CLEAR fileno */
|
|
||||||
if (fd != _NO_CONSOLE_FILENO) {
|
|
||||||
/* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that. Instead
|
|
||||||
* we check pointer validity and other info
|
|
||||||
*/
|
|
||||||
if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
|
|
||||||
/* finally, check that the file is open */
|
|
||||||
my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
|
|
||||||
if (info->osfile & FOPEN) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fail:
|
|
||||||
errno = EBADF;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the special case of checking dup2. The target fd must be in a sensible range */
|
/* the special case of checking dup2. The target fd must be in a sensible range */
|
||||||
static int
|
static int
|
||||||
_PyVerify_fd_dup2(int fd1, int fd2)
|
_PyVerify_fd_dup2(int fd1, int fd2)
|
||||||
|
@ -1158,8 +1075,7 @@ _PyVerify_fd_dup2(int fd1, int fd2)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* dummy version. _PyVerify_fd() is already defined in fileobject.h */
|
#define _PyVerify_fd_dup2(fd1, fd2) (_PyVerify_fd(fd1) && (fd2) >= 0)
|
||||||
#define _PyVerify_fd_dup2(A, B) (1)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1900
|
||||||
|
/* pyconfig.h uses this function in the _Py_BEGIN/END_SUPPRESS_IPH
|
||||||
|
* macros. It does not need to be defined when building using MSVC
|
||||||
|
* earlier than 14.0 (_MSC_VER == 1900).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void __cdecl _silent_invalid_parameter_handler(
|
||||||
|
wchar_t const* expression,
|
||||||
|
wchar_t const* function,
|
||||||
|
wchar_t const* file,
|
||||||
|
unsigned int line,
|
||||||
|
uintptr_t pReserved) { }
|
||||||
|
|
||||||
|
void *_Py_silent_invalid_parameter_handler =
|
||||||
|
(void*)_silent_invalid_parameter_handler;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -333,6 +333,7 @@
|
||||||
<ClCompile Include="..\Parser\parser.c" />
|
<ClCompile Include="..\Parser\parser.c" />
|
||||||
<ClCompile Include="..\Parser\parsetok.c" />
|
<ClCompile Include="..\Parser\parsetok.c" />
|
||||||
<ClCompile Include="..\Parser\tokenizer.c" />
|
<ClCompile Include="..\Parser\tokenizer.c" />
|
||||||
|
<ClCompile Include="..\PC\invalid_parameter_handler.c" />
|
||||||
<ClCompile Include="..\PC\winreg.c" />
|
<ClCompile Include="..\PC\winreg.c" />
|
||||||
<ClCompile Include="..\PC\config.c" />
|
<ClCompile Include="..\PC\config.c" />
|
||||||
<ClCompile Include="..\PC\getpathp.c" />
|
<ClCompile Include="..\PC\getpathp.c" />
|
||||||
|
@ -394,25 +395,21 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|
||||||
<Target Name="_GetBuildInfo" BeforeTargets="PrepareForBuild">
|
<Target Name="_GetBuildInfo" BeforeTargets="PrepareForBuild">
|
||||||
<Exec Command='hg id -b > "$(IntDir)hgbranch.txt"' ContinueOnError="true" />
|
<Exec Command="hg id -b > "$(IntDir)hgbranch.txt"" ContinueOnError="true" />
|
||||||
<Exec Command='hg id -i > "$(IntDir)hgversion.txt"' ContinueOnError="true" />
|
<Exec Command="hg id -i > "$(IntDir)hgversion.txt"" ContinueOnError="true" />
|
||||||
<Exec Command='hg id -t > "$(IntDir)hgtag.txt"' ContinueOnError="true" />
|
<Exec Command="hg id -t > "$(IntDir)hgtag.txt"" ContinueOnError="true" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<HgBranch Condition="Exists('$(IntDir)hgbranch.txt')">$([System.IO.File]::ReadAllText('$(IntDir)hgbranch.txt').Trim())</HgBranch>
|
<HgBranch Condition="Exists('$(IntDir)hgbranch.txt')">$([System.IO.File]::ReadAllText('$(IntDir)hgbranch.txt').Trim())</HgBranch>
|
||||||
<HgVersion Condition="Exists('$(IntDir)hgversion.txt')">$([System.IO.File]::ReadAllText('$(IntDir)hgversion.txt').Trim())</HgVersion>
|
<HgVersion Condition="Exists('$(IntDir)hgversion.txt')">$([System.IO.File]::ReadAllText('$(IntDir)hgversion.txt').Trim())</HgVersion>
|
||||||
<HgTag Condition="Exists('$(IntDir)hgtag.txt')">$([System.IO.File]::ReadAllText('$(IntDir)hgtag.txt').Trim())</HgTag>
|
<HgTag Condition="Exists('$(IntDir)hgtag.txt')">$([System.IO.File]::ReadAllText('$(IntDir)hgtag.txt').Trim())</HgTag>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\Modules\getbuildinfo.c">
|
<ClCompile Include="..\Modules\getbuildinfo.c">
|
||||||
<PreprocessorDefinitions>HGVERSION="$(HgVersion)";HGTAG="$(HgTag)";HGBRANCH="$(HgBranch)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>HGVERSION="$(HgVersion)";HGTAG="$(HgTag)";HGBRANCH="$(HgBranch)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="_WarnAboutToolset" BeforeTargets="PrepareForBuild" Condition="$(PlatformToolset) != 'v140'">
|
<Target Name="_WarnAboutToolset" BeforeTargets="PrepareForBuild" Condition="$(PlatformToolset) != 'v140'">
|
||||||
<Warning Text="Toolset $(PlatformToolset) is not used for official builds. Your build may have errors or incompatibilities." />
|
<Warning Text="Toolset $(PlatformToolset) is not used for official builds. Your build may have errors or incompatibilities." />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
|
@ -959,6 +959,9 @@
|
||||||
<ClCompile Include="..\Modules\hashtable.c">
|
<ClCompile Include="..\Modules\hashtable.c">
|
||||||
<Filter>Modules</Filter>
|
<Filter>Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\PC\invalid_parameter_handler.c">
|
||||||
|
<Filter>PC</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\PC\python_nt.rc">
|
<ResourceCompile Include="..\PC\python_nt.rc">
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
# include <malloc.h>
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -636,14 +637,10 @@ _Py_fstat(int fd, struct _Py_stat_struct *result)
|
||||||
else
|
else
|
||||||
h = (HANDLE)_get_osfhandle(fd);
|
h = (HANDLE)_get_osfhandle(fd);
|
||||||
|
|
||||||
/* Protocol violation: we explicitly clear errno, instead of
|
|
||||||
setting it to a POSIX error. Callers should use GetLastError. */
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
/* This is really a C library error (invalid file handle).
|
errno = EBADF;
|
||||||
We set the Win32 error to the closes one matching. */
|
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(result, 0, sizeof(*result));
|
memset(result, 0, sizeof(*result));
|
||||||
|
@ -652,6 +649,7 @@ _Py_fstat(int fd, struct _Py_stat_struct *result)
|
||||||
if (type == FILE_TYPE_UNKNOWN) {
|
if (type == FILE_TYPE_UNKNOWN) {
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* else: valid but unknown file */
|
/* else: valid but unknown file */
|
||||||
|
@ -666,6 +664,7 @@ _Py_fstat(int fd, struct _Py_stat_struct *result)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetFileInformationByHandle(h, &info)) {
|
if (!GetFileInformationByHandle(h, &info)) {
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,3 +1266,102 @@ error:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if _MSC_VER >= 1900
|
||||||
|
|
||||||
|
/* This function lets the Windows CRT validate the file handle without
|
||||||
|
terminating the process if it's invalid. */
|
||||||
|
int
|
||||||
|
_PyVerify_fd(int fd)
|
||||||
|
{
|
||||||
|
intptr_t osh;
|
||||||
|
/* Fast check for the only condition we know */
|
||||||
|
if (fd < 0) {
|
||||||
|
_set_errno(EBADF);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
osh = _get_osfhandle(fd);
|
||||||
|
return osh != (intptr_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif _MSC_VER >= 1400
|
||||||
|
/* Legacy implementation of _PyVerify_fd while transitioning to
|
||||||
|
* MSVC 14.0. This should eventually be removed. (issue23524)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
|
||||||
|
* valid and raise an assertion if it isn't.
|
||||||
|
* Normally, an invalid fd is likely to be a C program error and therefore
|
||||||
|
* an assertion can be useful, but it does contradict the POSIX standard
|
||||||
|
* which for write(2) states:
|
||||||
|
* "Otherwise, -1 shall be returned and errno set to indicate the error."
|
||||||
|
* "[EBADF] The fildes argument is not a valid file descriptor open for
|
||||||
|
* writing."
|
||||||
|
* Furthermore, python allows the user to enter any old integer
|
||||||
|
* as a fd and should merely raise a python exception on error.
|
||||||
|
* The Microsoft CRT doesn't provide an official way to check for the
|
||||||
|
* validity of a file descriptor, but we can emulate its internal behaviour
|
||||||
|
* by using the exported __pinfo data member and knowledge of the
|
||||||
|
* internal structures involved.
|
||||||
|
* The structures below must be updated for each version of visual studio
|
||||||
|
* according to the file internal.h in the CRT source, until MS comes
|
||||||
|
* up with a less hacky way to do this.
|
||||||
|
* (all of this is to avoid globally modifying the CRT behaviour using
|
||||||
|
* _set_invalid_parameter_handler() and _CrtSetReportMode())
|
||||||
|
*/
|
||||||
|
/* The actual size of the structure is determined at runtime.
|
||||||
|
* Only the first items must be present.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
intptr_t osfhnd;
|
||||||
|
char osfile;
|
||||||
|
} my_ioinfo;
|
||||||
|
|
||||||
|
extern __declspec(dllimport) char * __pioinfo[];
|
||||||
|
#define IOINFO_L2E 5
|
||||||
|
#define IOINFO_ARRAYS 64
|
||||||
|
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
|
||||||
|
#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
|
||||||
|
#define FOPEN 0x01
|
||||||
|
#define _NO_CONSOLE_FILENO (intptr_t)-2
|
||||||
|
|
||||||
|
/* This function emulates what the windows CRT does to validate file handles */
|
||||||
|
int
|
||||||
|
_PyVerify_fd(int fd)
|
||||||
|
{
|
||||||
|
const int i1 = fd >> IOINFO_L2E;
|
||||||
|
const int i2 = fd & ((1 << IOINFO_L2E) - 1);
|
||||||
|
|
||||||
|
static size_t sizeof_ioinfo = 0;
|
||||||
|
|
||||||
|
/* Determine the actual size of the ioinfo structure,
|
||||||
|
* as used by the CRT loaded in memory
|
||||||
|
*/
|
||||||
|
if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
|
||||||
|
sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
|
||||||
|
}
|
||||||
|
if (sizeof_ioinfo == 0) {
|
||||||
|
/* This should not happen... */
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See that it isn't a special CLEAR fileno */
|
||||||
|
if (fd != _NO_CONSOLE_FILENO) {
|
||||||
|
/* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that. Instead
|
||||||
|
* we check pointer validity and other info
|
||||||
|
*/
|
||||||
|
if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
|
||||||
|
/* finally, check that the file is open */
|
||||||
|
my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
|
||||||
|
if (info->osfile & FOPEN) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fail:
|
||||||
|
errno = EBADF;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _MSC_VER >= 1900 || _MSC_VER >= 1400 */
|
||||||
|
#endif /* defined _MSC_VER */
|
||||||
|
|
|
@ -22,6 +22,12 @@ to avoid the expense of doing their own locking).
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined _MSC_VER && _MSC_VER >= 1900
|
||||||
|
/* Issue #23524: Temporary fix to disable termination due to invalid parameters */
|
||||||
|
PyAPI_DATA(void*) _Py_silent_invalid_parameter_handler;
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -222,6 +228,11 @@ new_threadstate(PyInterpreterState *interp, int init)
|
||||||
tstate->next->prev = tstate;
|
tstate->next->prev = tstate;
|
||||||
interp->tstate_head = tstate;
|
interp->tstate_head = tstate;
|
||||||
HEAD_UNLOCK();
|
HEAD_UNLOCK();
|
||||||
|
|
||||||
|
#if defined _MSC_VER && _MSC_VER >= 1900
|
||||||
|
/* Issue #23524: Temporary fix to disable termination due to invalid parameters */
|
||||||
|
_set_thread_local_invalid_parameter_handler((_invalid_parameter_handler)_Py_silent_invalid_parameter_handler);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return tstate;
|
return tstate;
|
||||||
|
|
Loading…
Reference in New Issue