mirror of https://github.com/python/cpython
bpo-30555: Fix WindowsConsoleIO fails in the presence of fd redirection (GH-1927)
This works by not caching the handle and instead getting the handle from the file descriptor each time, so that if the actual handle changes by fd redirection closing/opening the console handle beneath our feet, we will keep working correctly.
This commit is contained in:
parent
6b59e662fa
commit
5e437fb872
|
@ -161,4 +161,12 @@ PyAPI_FUNC(int) _Py_dup(int fd);
|
||||||
PyAPI_FUNC(int) _Py_get_blocking(int fd);
|
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 */
|
#else /* MS_WINDOWS */
|
||||||
|
PyAPI_FUNC(void*) _Py_get_osfhandle_noraise(int fd);
|
||||||
|
|
||||||
|
PyAPI_FUNC(void*) _Py_get_osfhandle(int fd);
|
||||||
|
|
||||||
|
PyAPI_FUNC(int) _Py_open_osfhandle_noraise(void *handle, int flags);
|
||||||
|
|
||||||
|
PyAPI_FUNC(int) _Py_open_osfhandle(void *handle, int flags);
|
||||||
|
#endif /* MS_WINDOWS */
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix ``WindowsConsoleIO`` errors in the presence of fd redirection. Patch by
|
||||||
|
Segev Finer.
|
|
@ -8,10 +8,10 @@ PyDoc_STRVAR(_io__WindowsConsoleIO_close__doc__,
|
||||||
"close($self, /)\n"
|
"close($self, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Close the handle.\n"
|
"Close the console object.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"A closed handle cannot be used for further I/O operations. close() may be\n"
|
"A closed console object cannot be used for further I/O operations.\n"
|
||||||
"called more than once without error.");
|
"close() may be called more than once without error.");
|
||||||
|
|
||||||
#define _IO__WINDOWSCONSOLEIO_CLOSE_METHODDEF \
|
#define _IO__WINDOWSCONSOLEIO_CLOSE_METHODDEF \
|
||||||
{"close", (PyCFunction)_io__WindowsConsoleIO_close, METH_NOARGS, _io__WindowsConsoleIO_close__doc__},
|
{"close", (PyCFunction)_io__WindowsConsoleIO_close, METH_NOARGS, _io__WindowsConsoleIO_close__doc__},
|
||||||
|
@ -110,10 +110,7 @@ PyDoc_STRVAR(_io__WindowsConsoleIO_fileno__doc__,
|
||||||
"fileno($self, /)\n"
|
"fileno($self, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return the underlying file descriptor (an integer).\n"
|
"Return the underlying file descriptor (an integer).");
|
||||||
"\n"
|
|
||||||
"fileno is only set when a file descriptor is used to open\n"
|
|
||||||
"one of the standard streams.");
|
|
||||||
|
|
||||||
#define _IO__WINDOWSCONSOLEIO_FILENO_METHODDEF \
|
#define _IO__WINDOWSCONSOLEIO_FILENO_METHODDEF \
|
||||||
{"fileno", (PyCFunction)_io__WindowsConsoleIO_fileno, METH_NOARGS, _io__WindowsConsoleIO_fileno__doc__},
|
{"fileno", (PyCFunction)_io__WindowsConsoleIO_fileno, METH_NOARGS, _io__WindowsConsoleIO_fileno__doc__},
|
||||||
|
@ -381,4 +378,4 @@ _io__WindowsConsoleIO_isatty(winconsoleio *self, PyObject *Py_UNUSED(ignored))
|
||||||
#ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF
|
#ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF
|
||||||
#define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF
|
#define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF
|
||||||
#endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */
|
#endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */
|
||||||
/*[clinic end generated code: output=a28b3120fa53b256 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=48080572ffee22f5 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -64,10 +64,7 @@ char _PyIO_get_console_type(PyObject *path_or_fd) {
|
||||||
int fd = PyLong_AsLong(path_or_fd);
|
int fd = PyLong_AsLong(path_or_fd);
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
HANDLE handle;
|
HANDLE handle = _Py_get_osfhandle_noraise(fd);
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
|
||||||
handle = (HANDLE)_get_osfhandle(fd);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
return '\0';
|
return '\0';
|
||||||
return _get_console_type(handle);
|
return _get_console_type(handle);
|
||||||
|
@ -143,12 +140,11 @@ class _io._WindowsConsoleIO "winconsoleio *" "&PyWindowsConsoleIO_Type"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
HANDLE handle;
|
|
||||||
int fd;
|
int fd;
|
||||||
unsigned int created : 1;
|
unsigned int created : 1;
|
||||||
unsigned int readable : 1;
|
unsigned int readable : 1;
|
||||||
unsigned int writable : 1;
|
unsigned int writable : 1;
|
||||||
unsigned int closehandle : 1;
|
unsigned int closefd : 1;
|
||||||
char finalizing;
|
char finalizing;
|
||||||
unsigned int blksize;
|
unsigned int blksize;
|
||||||
PyObject *weakreflist;
|
PyObject *weakreflist;
|
||||||
|
@ -164,7 +160,7 @@ _Py_IDENTIFIER(name);
|
||||||
int
|
int
|
||||||
_PyWindowsConsoleIO_closed(PyObject *self)
|
_PyWindowsConsoleIO_closed(PyObject *self)
|
||||||
{
|
{
|
||||||
return ((winconsoleio *)self)->handle == INVALID_HANDLE_VALUE;
|
return ((winconsoleio *)self)->fd == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,16 +168,12 @@ _PyWindowsConsoleIO_closed(PyObject *self)
|
||||||
static int
|
static int
|
||||||
internal_close(winconsoleio *self)
|
internal_close(winconsoleio *self)
|
||||||
{
|
{
|
||||||
if (self->handle != INVALID_HANDLE_VALUE) {
|
if (self->fd != -1) {
|
||||||
if (self->closehandle) {
|
if (self->closefd) {
|
||||||
if (self->fd >= 0) {
|
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
_Py_BEGIN_SUPPRESS_IPH
|
||||||
close(self->fd);
|
close(self->fd);
|
||||||
_Py_END_SUPPRESS_IPH
|
_Py_END_SUPPRESS_IPH
|
||||||
}
|
}
|
||||||
CloseHandle(self->handle);
|
|
||||||
}
|
|
||||||
self->handle = INVALID_HANDLE_VALUE;
|
|
||||||
self->fd = -1;
|
self->fd = -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -190,15 +182,15 @@ internal_close(winconsoleio *self)
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_io._WindowsConsoleIO.close
|
_io._WindowsConsoleIO.close
|
||||||
|
|
||||||
Close the handle.
|
Close the console object.
|
||||||
|
|
||||||
A closed handle cannot be used for further I/O operations. close() may be
|
A closed console object cannot be used for further I/O operations.
|
||||||
called more than once without error.
|
close() may be called more than once without error.
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_io__WindowsConsoleIO_close_impl(winconsoleio *self)
|
_io__WindowsConsoleIO_close_impl(winconsoleio *self)
|
||||||
/*[clinic end generated code: output=27ef95b66c29057b input=185617e349ae4c7b]*/
|
/*[clinic end generated code: output=27ef95b66c29057b input=68c4e5754f8136c2]*/
|
||||||
{
|
{
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
PyObject *exc, *val, *tb;
|
PyObject *exc, *val, *tb;
|
||||||
|
@ -206,8 +198,8 @@ _io__WindowsConsoleIO_close_impl(winconsoleio *self)
|
||||||
_Py_IDENTIFIER(close);
|
_Py_IDENTIFIER(close);
|
||||||
res = _PyObject_CallMethodIdOneArg((PyObject*)&PyRawIOBase_Type,
|
res = _PyObject_CallMethodIdOneArg((PyObject*)&PyRawIOBase_Type,
|
||||||
&PyId_close, (PyObject*)self);
|
&PyId_close, (PyObject*)self);
|
||||||
if (!self->closehandle) {
|
if (!self->closefd) {
|
||||||
self->handle = INVALID_HANDLE_VALUE;
|
self->fd = -1;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
|
@ -229,12 +221,11 @@ winconsoleio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
|
|
||||||
self = (winconsoleio *) type->tp_alloc(type, 0);
|
self = (winconsoleio *) type->tp_alloc(type, 0);
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
self->handle = INVALID_HANDLE_VALUE;
|
|
||||||
self->fd = -1;
|
self->fd = -1;
|
||||||
self->created = 0;
|
self->created = 0;
|
||||||
self->readable = 0;
|
self->readable = 0;
|
||||||
self->writable = 0;
|
self->writable = 0;
|
||||||
self->closehandle = 0;
|
self->closefd = 0;
|
||||||
self->blksize = 0;
|
self->blksize = 0;
|
||||||
self->weakreflist = NULL;
|
self->weakreflist = NULL;
|
||||||
}
|
}
|
||||||
|
@ -269,16 +260,17 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
|
||||||
int rwa = 0;
|
int rwa = 0;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int fd_is_own = 0;
|
int fd_is_own = 0;
|
||||||
|
HANDLE handle = NULL;
|
||||||
|
|
||||||
assert(PyWindowsConsoleIO_Check(self));
|
assert(PyWindowsConsoleIO_Check(self));
|
||||||
if (self->handle >= 0) {
|
if (self->fd >= 0) {
|
||||||
if (self->closehandle) {
|
if (self->closefd) {
|
||||||
/* Have to close the existing file first. */
|
/* Have to close the existing file first. */
|
||||||
if (internal_close(self) < 0)
|
if (internal_close(self) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
self->handle = INVALID_HANDLE_VALUE;
|
self->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = _PyLong_AsInt(nameobj);
|
fd = _PyLong_AsInt(nameobj);
|
||||||
|
@ -341,14 +333,12 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
|
||||||
goto bad_mode;
|
goto bad_mode;
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
handle = _Py_get_osfhandle_noraise(fd);
|
||||||
self->handle = (HANDLE)_get_osfhandle(fd);
|
self->closefd = 0;
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
self->closehandle = 0;
|
|
||||||
} else {
|
} else {
|
||||||
DWORD access = GENERIC_READ;
|
DWORD access = GENERIC_READ;
|
||||||
|
|
||||||
self->closehandle = 1;
|
self->closefd = 1;
|
||||||
if (!closefd) {
|
if (!closefd) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Cannot use closefd=False with file name");
|
"Cannot use closefd=False with file name");
|
||||||
|
@ -363,21 +353,31 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
|
||||||
on the specific access. This is required for modern names
|
on the specific access. This is required for modern names
|
||||||
CONIN$ and CONOUT$, which allow reading/writing state as
|
CONIN$ and CONOUT$, which allow reading/writing state as
|
||||||
well as reading/writing content. */
|
well as reading/writing content. */
|
||||||
self->handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
|
handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
self->handle = CreateFileW(name, access,
|
handle = CreateFileW(name, access,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
if (self->handle == INVALID_HANDLE_VALUE) {
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, GetLastError(), nameobj);
|
PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, GetLastError(), nameobj);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->writable)
|
||||||
|
self->fd = _Py_open_osfhandle_noraise(handle, _O_WRONLY | _O_BINARY);
|
||||||
|
else
|
||||||
|
self->fd = _Py_open_osfhandle_noraise(handle, _O_RDONLY | _O_BINARY);
|
||||||
|
if (self->fd < 0) {
|
||||||
|
CloseHandle(handle);
|
||||||
|
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (console_type == '\0')
|
if (console_type == '\0')
|
||||||
console_type = _get_console_type(self->handle);
|
console_type = _get_console_type(handle);
|
||||||
|
|
||||||
if (self->writable && console_type != 'w') {
|
if (self->writable && console_type != 'w') {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
@ -460,25 +460,14 @@ _io._WindowsConsoleIO.fileno
|
||||||
|
|
||||||
Return the underlying file descriptor (an integer).
|
Return the underlying file descriptor (an integer).
|
||||||
|
|
||||||
fileno is only set when a file descriptor is used to open
|
|
||||||
one of the standard streams.
|
|
||||||
|
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_io__WindowsConsoleIO_fileno_impl(winconsoleio *self)
|
_io__WindowsConsoleIO_fileno_impl(winconsoleio *self)
|
||||||
/*[clinic end generated code: output=006fa74ce3b5cfbf input=079adc330ddaabe6]*/
|
/*[clinic end generated code: output=006fa74ce3b5cfbf input=845c47ebbc3a2f67]*/
|
||||||
{
|
{
|
||||||
if (self->fd < 0 && self->handle != INVALID_HANDLE_VALUE) {
|
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
|
||||||
if (self->writable)
|
|
||||||
self->fd = _open_osfhandle((intptr_t)self->handle, _O_WRONLY | _O_BINARY);
|
|
||||||
else
|
|
||||||
self->fd = _open_osfhandle((intptr_t)self->handle, _O_RDONLY | _O_BINARY);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
}
|
|
||||||
if (self->fd < 0)
|
if (self->fd < 0)
|
||||||
return err_mode("fileno");
|
return err_closed();
|
||||||
return PyLong_FromLong(self->fd);
|
return PyLong_FromLong(self->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +481,7 @@ static PyObject *
|
||||||
_io__WindowsConsoleIO_readable_impl(winconsoleio *self)
|
_io__WindowsConsoleIO_readable_impl(winconsoleio *self)
|
||||||
/*[clinic end generated code: output=daf9cef2743becf0 input=6be9defb5302daae]*/
|
/*[clinic end generated code: output=daf9cef2743becf0 input=6be9defb5302daae]*/
|
||||||
{
|
{
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (self->fd == -1)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
return PyBool_FromLong((long) self->readable);
|
return PyBool_FromLong((long) self->readable);
|
||||||
}
|
}
|
||||||
|
@ -507,7 +496,7 @@ static PyObject *
|
||||||
_io__WindowsConsoleIO_writable_impl(winconsoleio *self)
|
_io__WindowsConsoleIO_writable_impl(winconsoleio *self)
|
||||||
/*[clinic end generated code: output=e0a2ad7eae5abf67 input=cefbd8abc24df6a0]*/
|
/*[clinic end generated code: output=e0a2ad7eae5abf67 input=cefbd8abc24df6a0]*/
|
||||||
{
|
{
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (self->fd == -1)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
return PyBool_FromLong((long) self->writable);
|
return PyBool_FromLong((long) self->writable);
|
||||||
}
|
}
|
||||||
|
@ -642,7 +631,7 @@ error:
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
readinto(winconsoleio *self, char *buf, Py_ssize_t len)
|
readinto(winconsoleio *self, char *buf, Py_ssize_t len)
|
||||||
{
|
{
|
||||||
if (self->handle == INVALID_HANDLE_VALUE) {
|
if (self->fd == -1) {
|
||||||
err_closed();
|
err_closed();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -657,6 +646,10 @@ readinto(winconsoleio *self, char *buf, Py_ssize_t len)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE handle = _Py_get_osfhandle(self->fd);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* Each character may take up to 4 bytes in the final buffer.
|
/* Each character may take up to 4 bytes in the final buffer.
|
||||||
This is highly conservative, but necessary to avoid
|
This is highly conservative, but necessary to avoid
|
||||||
failure for any given Unicode input (e.g. \U0010ffff).
|
failure for any given Unicode input (e.g. \U0010ffff).
|
||||||
|
@ -678,7 +671,7 @@ readinto(winconsoleio *self, char *buf, Py_ssize_t len)
|
||||||
return read_len;
|
return read_len;
|
||||||
|
|
||||||
DWORD n;
|
DWORD n;
|
||||||
wchar_t *wbuf = read_console_w(self->handle, wlen, &n);
|
wchar_t *wbuf = read_console_w(handle, wlen, &n);
|
||||||
if (wbuf == NULL)
|
if (wbuf == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
|
@ -784,10 +777,15 @@ _io__WindowsConsoleIO_readall_impl(winconsoleio *self)
|
||||||
DWORD bufsize, n, len = 0;
|
DWORD bufsize, n, len = 0;
|
||||||
PyObject *bytes;
|
PyObject *bytes;
|
||||||
DWORD bytes_size, rn;
|
DWORD bytes_size, rn;
|
||||||
|
HANDLE handle;
|
||||||
|
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (self->fd == -1)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
|
|
||||||
|
handle = _Py_get_osfhandle(self->fd);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
bufsize = BUFSIZ;
|
bufsize = BUFSIZ;
|
||||||
|
|
||||||
buf = (wchar_t*)PyMem_Malloc((bufsize + 1) * sizeof(wchar_t));
|
buf = (wchar_t*)PyMem_Malloc((bufsize + 1) * sizeof(wchar_t));
|
||||||
|
@ -819,7 +817,7 @@ _io__WindowsConsoleIO_readall_impl(winconsoleio *self)
|
||||||
buf = tmp;
|
buf = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
subbuf = read_console_w(self->handle, bufsize - len, &n);
|
subbuf = read_console_w(handle, bufsize - len, &n);
|
||||||
|
|
||||||
if (subbuf == NULL) {
|
if (subbuf == NULL) {
|
||||||
PyMem_Free(buf);
|
PyMem_Free(buf);
|
||||||
|
@ -909,7 +907,7 @@ _io__WindowsConsoleIO_read_impl(winconsoleio *self, Py_ssize_t size)
|
||||||
PyObject *bytes;
|
PyObject *bytes;
|
||||||
Py_ssize_t bytes_size;
|
Py_ssize_t bytes_size;
|
||||||
|
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (self->fd == -1)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
if (!self->readable)
|
if (!self->readable)
|
||||||
return err_mode("reading");
|
return err_mode("reading");
|
||||||
|
@ -959,12 +957,17 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b)
|
||||||
BOOL res = TRUE;
|
BOOL res = TRUE;
|
||||||
wchar_t *wbuf;
|
wchar_t *wbuf;
|
||||||
DWORD len, wlen, n = 0;
|
DWORD len, wlen, n = 0;
|
||||||
|
HANDLE handle;
|
||||||
|
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (self->fd == -1)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
if (!self->writable)
|
if (!self->writable)
|
||||||
return err_mode("writing");
|
return err_mode("writing");
|
||||||
|
|
||||||
|
handle = _Py_get_osfhandle(self->fd);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (!b->len) {
|
if (!b->len) {
|
||||||
return PyLong_FromLong(0);
|
return PyLong_FromLong(0);
|
||||||
}
|
}
|
||||||
|
@ -995,7 +998,7 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b)
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
wlen = MultiByteToWideChar(CP_UTF8, 0, b->buf, len, wbuf, wlen);
|
wlen = MultiByteToWideChar(CP_UTF8, 0, b->buf, len, wbuf, wlen);
|
||||||
if (wlen) {
|
if (wlen) {
|
||||||
res = WriteConsoleW(self->handle, wbuf, wlen, &n, NULL);
|
res = WriteConsoleW(handle, wbuf, wlen, &n, NULL);
|
||||||
if (res && n < wlen) {
|
if (res && n < wlen) {
|
||||||
/* Wrote fewer characters than expected, which means our
|
/* Wrote fewer characters than expected, which means our
|
||||||
* len value may be wrong. So recalculate it from the
|
* len value may be wrong. So recalculate it from the
|
||||||
|
@ -1027,15 +1030,15 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
winconsoleio_repr(winconsoleio *self)
|
winconsoleio_repr(winconsoleio *self)
|
||||||
{
|
{
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (self->fd == -1)
|
||||||
return PyUnicode_FromFormat("<_io._WindowsConsoleIO [closed]>");
|
return PyUnicode_FromFormat("<_io._WindowsConsoleIO [closed]>");
|
||||||
|
|
||||||
if (self->readable)
|
if (self->readable)
|
||||||
return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='rb' closefd=%s>",
|
return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='rb' closefd=%s>",
|
||||||
self->closehandle ? "True" : "False");
|
self->closefd ? "True" : "False");
|
||||||
if (self->writable)
|
if (self->writable)
|
||||||
return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='wb' closefd=%s>",
|
return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='wb' closefd=%s>",
|
||||||
self->closehandle ? "True" : "False");
|
self->closefd ? "True" : "False");
|
||||||
|
|
||||||
PyErr_SetString(PyExc_SystemError, "_WindowsConsoleIO has invalid mode");
|
PyErr_SetString(PyExc_SystemError, "_WindowsConsoleIO has invalid mode");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1051,7 +1054,7 @@ static PyObject *
|
||||||
_io__WindowsConsoleIO_isatty_impl(winconsoleio *self)
|
_io__WindowsConsoleIO_isatty_impl(winconsoleio *self)
|
||||||
/*[clinic end generated code: output=9eac09d287c11bd7 input=9b91591dbe356f86]*/
|
/*[clinic end generated code: output=9eac09d287c11bd7 input=9b91591dbe356f86]*/
|
||||||
{
|
{
|
||||||
if (self->handle == INVALID_HANDLE_VALUE)
|
if (self->fd == -1)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
|
|
||||||
Py_RETURN_TRUE;
|
Py_RETURN_TRUE;
|
||||||
|
@ -1077,13 +1080,13 @@ static PyMethodDef winconsoleio_methods[] = {
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_closed(winconsoleio *self, void *closure)
|
get_closed(winconsoleio *self, void *closure)
|
||||||
{
|
{
|
||||||
return PyBool_FromLong((long)(self->handle == INVALID_HANDLE_VALUE));
|
return PyBool_FromLong((long)(self->fd == -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_closefd(winconsoleio *self, void *closure)
|
get_closefd(winconsoleio *self, void *closure)
|
||||||
{
|
{
|
||||||
return PyBool_FromLong((long)(self->closehandle));
|
return PyBool_FromLong((long)(self->closefd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
|
@ -1370,13 +1370,10 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
|
||||||
*/
|
*/
|
||||||
if (fileno != -1 && fileno != 0) {
|
if (fileno != -1 && fileno != 0) {
|
||||||
/* Ensure that fileno is within the CRT's valid range */
|
/* Ensure that fileno is within the CRT's valid range */
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
fh = _Py_get_osfhandle(fileno);
|
||||||
fh = (HANDLE)_get_osfhandle(fileno);
|
if (fh == INVALID_HANDLE_VALUE)
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
if (fh==(HANDLE)-1) {
|
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
/* Win9x appears to need us seeked to zero */
|
/* Win9x appears to need us seeked to zero */
|
||||||
lseek(fileno, 0, SEEK_SET);
|
lseek(fileno, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10098,18 +10098,16 @@ os_pipe_impl(PyObject *module)
|
||||||
attr.bInheritHandle = FALSE;
|
attr.bInheritHandle = FALSE;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
|
||||||
ok = CreatePipe(&read, &write, &attr, 0);
|
ok = CreatePipe(&read, &write, &attr, 0);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
|
fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
|
||||||
fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
|
fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
|
||||||
if (fds[0] == -1 || fds[1] == -1) {
|
if (fds[0] == -1 || fds[1] == -1) {
|
||||||
CloseHandle(read);
|
CloseHandle(read);
|
||||||
CloseHandle(write);
|
CloseHandle(write);
|
||||||
ok = 0;
|
ok = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
/* The full definition is in iomodule. We reproduce
|
/* The full definition is in iomodule. We reproduce
|
||||||
enough here to get the handle, which is all we want. */
|
enough here to get the fd, which is all we want. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
HANDLE handle;
|
int fd;
|
||||||
} winconsoleio;
|
} winconsoleio;
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,7 +67,10 @@ _testconsole_write_input_impl(PyObject *module, PyObject *file,
|
||||||
prec->Event.KeyEvent.uChar.UnicodeChar = *p;
|
prec->Event.KeyEvent.uChar.UnicodeChar = *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE hInput = ((winconsoleio*)file)->handle;
|
HANDLE hInput = _Py_get_osfhandle(((winconsoleio*)file)->fd);
|
||||||
|
if (hInput == INVALID_HANDLE_VALUE)
|
||||||
|
goto error;
|
||||||
|
|
||||||
DWORD total = 0;
|
DWORD total = 0;
|
||||||
while (total < size) {
|
while (total < size) {
|
||||||
DWORD wrote;
|
DWORD wrote;
|
||||||
|
|
|
@ -177,19 +177,11 @@ static long
|
||||||
msvcrt_open_osfhandle_impl(PyObject *module, void *handle, int flags)
|
msvcrt_open_osfhandle_impl(PyObject *module, void *handle, int flags)
|
||||||
/*[clinic end generated code: output=b2fb97c4b515e4e6 input=d5db190a307cf4bb]*/
|
/*[clinic end generated code: output=b2fb97c4b515e4e6 input=d5db190a307cf4bb]*/
|
||||||
{
|
{
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (PySys_Audit("msvcrt.open_osfhandle", "Ki", handle, flags) < 0) {
|
if (PySys_Audit("msvcrt.open_osfhandle", "Ki", handle, flags) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
return _Py_open_osfhandle(handle, flags);
|
||||||
fd = _open_osfhandle((intptr_t)handle, flags);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
if (fd == -1)
|
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
@ -207,19 +199,11 @@ static void *
|
||||||
msvcrt_get_osfhandle_impl(PyObject *module, int fd)
|
msvcrt_get_osfhandle_impl(PyObject *module, int fd)
|
||||||
/*[clinic end generated code: output=aca01dfe24637374 input=5fcfde9b17136aa2]*/
|
/*[clinic end generated code: output=aca01dfe24637374 input=5fcfde9b17136aa2]*/
|
||||||
{
|
{
|
||||||
intptr_t handle = -1;
|
|
||||||
|
|
||||||
if (PySys_Audit("msvcrt.get_osfhandle", "(i)", fd) < 0) {
|
if (PySys_Audit("msvcrt.get_osfhandle", "(i)", fd) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
return _Py_get_osfhandle(fd);
|
||||||
handle = _get_osfhandle(fd);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
if (handle == -1)
|
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
|
||||||
|
|
||||||
return (HANDLE)handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Console I/O */
|
/* Console I/O */
|
||||||
|
|
|
@ -249,10 +249,8 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
||||||
if (!Py_LegacyWindowsStdioFlag && sys_stdin == stdin) {
|
if (!Py_LegacyWindowsStdioFlag && sys_stdin == stdin) {
|
||||||
HANDLE hStdIn, hStdErr;
|
HANDLE hStdIn, hStdErr;
|
||||||
|
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
hStdIn = _Py_get_osfhandle_noraise(fileno(sys_stdin));
|
||||||
hStdIn = (HANDLE)_get_osfhandle(fileno(sys_stdin));
|
hStdErr = _Py_get_osfhandle_noraise(fileno(stderr));
|
||||||
hStdErr = (HANDLE)_get_osfhandle(fileno(stderr));
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
|
|
||||||
if (_get_console_type(hStdIn) == 'r') {
|
if (_get_console_type(hStdIn) == 'r') {
|
||||||
fflush(sys_stdout);
|
fflush(sys_stdout);
|
||||||
|
|
|
@ -1016,9 +1016,7 @@ _Py_fstat_noraise(int fd, struct _Py_stat_struct *status)
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
h = _Py_get_osfhandle_noraise(fd);
|
||||||
h = (HANDLE)_get_osfhandle(fd);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
|
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
/* errno is already set by _get_osfhandle, but we also set
|
/* errno is already set by _get_osfhandle, but we also set
|
||||||
|
@ -1157,9 +1155,7 @@ get_inheritable(int fd, int raise)
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
|
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
handle = _Py_get_osfhandle_noraise(fd);
|
||||||
handle = (HANDLE)_get_osfhandle(fd);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
if (raise)
|
if (raise)
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
@ -1230,9 +1226,7 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
handle = _Py_get_osfhandle_noraise(fd);
|
||||||
handle = (HANDLE)_get_osfhandle(fd);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
if (raise)
|
if (raise)
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
@ -2006,13 +2000,9 @@ _Py_dup(int fd)
|
||||||
assert(PyGILState_Check());
|
assert(PyGILState_Check());
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
handle = _Py_get_osfhandle(fd);
|
||||||
handle = (HANDLE)_get_osfhandle(fd);
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
_Py_BEGIN_SUPPRESS_IPH
|
||||||
|
@ -2122,8 +2112,47 @@ error:
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#else /* MS_WINDOWS */
|
||||||
|
void*
|
||||||
|
_Py_get_osfhandle_noraise(int fd)
|
||||||
|
{
|
||||||
|
void *handle;
|
||||||
|
_Py_BEGIN_SUPPRESS_IPH
|
||||||
|
handle = (void*)_get_osfhandle(fd);
|
||||||
|
_Py_END_SUPPRESS_IPH
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
_Py_get_osfhandle(int fd)
|
||||||
|
{
|
||||||
|
void *handle = _Py_get_osfhandle_noraise(fd);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_Py_open_osfhandle_noraise(void *handle, int flags)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
_Py_BEGIN_SUPPRESS_IPH
|
||||||
|
fd = _open_osfhandle((intptr_t)handle, flags);
|
||||||
|
_Py_END_SUPPRESS_IPH
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_Py_open_osfhandle(void *handle, int flags)
|
||||||
|
{
|
||||||
|
int fd = _Py_open_osfhandle_noraise(handle, flags);
|
||||||
|
if (fd == -1)
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
#endif /* MS_WINDOWS */
|
||||||
|
|
||||||
int
|
int
|
||||||
_Py_GetLocaleconvNumeric(struct lconv *lc,
|
_Py_GetLocaleconvNumeric(struct lconv *lc,
|
||||||
|
|
Loading…
Reference in New Issue