diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index a78fa4d7d919fff..0e71a029390c407 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -125,6 +125,14 @@ def test_write_empty_data(self): with ConIO('CONOUT$', 'w') as f: self.assertEqual(f.write(b''), 0) + def test_fileno_raises_correct_exception(self): + # Test that WindowsConsoleIO implementation of fileno + # raises a ValueError instead of io.UnsupportedOperation + # if the internal handle value is INVALID_HANDLE_VALUE. + f = open('conin$', 'r') + f.close() + self.assertRaisesRegex(ValueError, "I/O operation on closed file", f.fileno) + def assertStdinRoundTrip(self, text): stdin = open('CONIN$', 'r') old_stdin = sys.stdin diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 13342ec239d6d66..ab8ccaf8b25a84c 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -474,7 +474,11 @@ static PyObject * _io__WindowsConsoleIO_fileno_impl(winconsoleio *self) /*[clinic end generated code: output=006fa74ce3b5cfbf input=079adc330ddaabe6]*/ { - if (self->fd < 0 && self->handle != INVALID_HANDLE_VALUE) { + if (self->handle == INVALID_HANDLE_VALUE) { + return err_closed(); + } + + if (self->fd < 0) { _Py_BEGIN_SUPPRESS_IPH if (self->writable) self->fd = _open_osfhandle((intptr_t)self->handle, _O_WRONLY | _O_BINARY); @@ -482,8 +486,13 @@ _io__WindowsConsoleIO_fileno_impl(winconsoleio *self) self->fd = _open_osfhandle((intptr_t)self->handle, _O_RDONLY | _O_BINARY); _Py_END_SUPPRESS_IPH } - if (self->fd < 0) - return err_mode("fileno"); + + if (self->fd < 0) { + if (self->closehandle) + CloseHandle(self->handle); + self->handle = INVALID_HANDLE_VALUE; + return err_closed(); + } return PyLong_FromLong(self->fd); }