Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSError: raw write() returned invalid length on latest Win 10 Consoles #76426

Closed
SimonDepiets mannequin opened this issue Dec 7, 2017 · 8 comments
Closed

OSError: raw write() returned invalid length on latest Win 10 Consoles #76426

SimonDepiets mannequin opened this issue Dec 7, 2017 · 8 comments
Labels
OS-windows topic-IO type-bug An unexpected behavior, bug, or error

Comments

@SimonDepiets
Copy link
Mannequin

SimonDepiets mannequin commented Dec 7, 2017

BPO 32245
Nosy @pfmoore, @tjguk, @zware, @eryksun, @zooba, @segevfiner

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2018-09-18.20:28:31.825>
created_at = <Date 2017-12-07.15:21:22.151>
labels = ['type-bug', 'expert-IO', 'OS-windows']
title = 'OSError: raw write() returned invalid length on latest Win 10 Consoles'
updated_at = <Date 2018-09-18.20:28:31.824>
user = 'https://bugs.python.org/SimonDepiets'

bugs.python.org fields:

activity = <Date 2018-09-18.20:28:31.824>
actor = 'eryksun'
assignee = 'none'
closed = True
closed_date = <Date 2018-09-18.20:28:31.825>
closer = 'eryksun'
components = ['Windows', 'IO']
creation = <Date 2017-12-07.15:21:22.151>
creator = 'Simon Depiets'
dependencies = []
files = []
hgrepos = []
issue_num = 32245
keywords = []
message_count = 8.0
messages = ['307811', '307918', '307920', '307926', '308012', '308088', '308595', '321350']
nosy_count = 7.0
nosy_names = ['paul.moore', 'tim.golden', 'zach.ware', 'eryksun', 'steve.dower', 'Segev Finer', 'Simon Depiets']
pr_nums = []
priority = 'normal'
resolution = 'third party'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue32245'
versions = ['Python 3.5', 'Python 3.6']

@SimonDepiets
Copy link
Mannequin Author

SimonDepiets mannequin commented Dec 7, 2017

A couple of users have been having issues on console output since the Fall 2017 Creator Update on Windows 10

An OSError is triggered randomly when rewriting data on the console (typically with progress bars, for instance when you install a module with pip), this only happens with the Microsoft Console (within Powershell or cmd.exe).

It seems the windows stdout console stream returns a length double what python expects. I don't have the skills to go deeper than the bufferedio.c method _bufferedwriter_raw_write to diagnostic the issue, so I've made a very dirty fix (which I do not recommend) 3.5...LlianeFR:patch-1

Different unrelated use cases where an error is triggered :

https://stackoverflow.com/questions/47356993/oserror-raw-write-returned-invalid-length-when-using-print-in-python

microsoft/vscode#39149

@SimonDepiets SimonDepiets mannequin added topic-IO type-bug An unexpected behavior, bug, or error labels Dec 7, 2017
@zooba
Copy link
Member

zooba commented Dec 9, 2017

Does this only affect Python 3.5? We're highly unlikely to take a fix for that version.

This code was rewritten for 3.6, so it wouldn't surprise me if there is no longer an issue.

@larryhastings
Copy link
Contributor

To confirm what Steve said: we no longer accept bug fixes for Python 3.5 (or 3.4). We only accept security fixes for 3.5 (and 3.4).

@eryksun
Copy link
Contributor

eryksun commented Dec 9, 2017

We need a test that reproduces this problem on a vanilla installation of Python 3.5. Include the system locale context as well, i.e. the ANSI codepage, OEM codepage, and active console output codepage. A reliable test will help determine whether this problem also affects legacy console I/O in Python 3.6. However, even if the problem affects 3.6, that doesn't mean there's anything we can reasonably do about it if the fault is the console host process (i.e. conhost.exe, running either ConhostV1.dll or the new ConhostV2.dll implementation).

A possible workaround in Python 3.5 would be to install and enable the win_unicode_console package. This package uses the console's native Unicode API instead of the legacy codepage API.

@SimonDepiets
Copy link
Mannequin Author

SimonDepiets mannequin commented Dec 11, 2017

The issue doesn't seem to happen on either 3.6 (with the new stdio mode) or with win_unicode_console enabled.

I was able to reproduce it on 3.6 with the PYTHONLEGACYWINDOWSSTDIO flag enabled, it's easier to trigger when using directional keys or mouse clicks within the console.

chcp : Active code page : 437

System locale : en-us

@eryksun
Copy link
Contributor

eryksun commented Dec 12, 2017

I was able to reproduce this problem in 3.6 in Windows 10 (1709), but only for code paths that call WriteFile, i.e. os.write and legacy standard I/O mode.

Writing to the console will block if there's an active text selection. The operation completes once the user copies the selection to the clipboard (e.g. by pressing enter). In the case of WriteFile, when the blocked call finally completes, the console mistakenly returns the number of internally written UTF-16 bytes.

This bug is not present with WriteConsoleA, which means there's a simple workaround. _Py_write could detect a console handle and call WriteConsoleA instead of _write.

The following test executes a write on a separate thread, after a timed delay that allows selecting text beforehand. Text can be selected via Ctrl+A, Shift+Up, or the mouse (the latter requires quick-edit mode or toggling mark mode).

    import os
    import sys
    import ctypes
    import msvcrt
    import threading

    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
    fd_stdout = sys.stdout.fileno()
    h_stdout = msvcrt.get_osfhandle(fd_stdout)
    n = ctypes.c_ulong()

    def test_write():
        n.value = os.write(fd_stdout, b'spam\r\n')

    def test_WriteFile():
        kernel32.WriteFile(h_stdout, b'spam\r\n', 6, ctypes.byref(n), None)

    def test_WriteConsoleA():
        kernel32.WriteConsoleA(h_stdout, b'spam\r\n', 6, ctypes.byref(n), None)

For example, given manual text selection after starting the timer:

>>> threading.Timer(5, test_write).start()
>>> spam
    >>> n
    c_ulong(12)
>>> threading.Timer(5, test_WriteFile).start()
>>> spam
    >>> n
    c_ulong(12)
>>> threading.Timer(5, test_WriteConsoleA).start()
>>> spam
    >>> n
    c_ulong(6)

This test could be completely automated by combining SendInput (to set the session control-key state), GetConsoleWindow, and PostMessageW (WM_KEYDOWN, WM_KEYUP).

@segevfiner
Copy link
Mannequin

segevfiner mannequin commented Dec 19, 2017

Upstream issue microsoft/terminal#40, also has links to similar issues this caused in other projects.

@segevfiner
Copy link
Mannequin

segevfiner mannequin commented Jul 9, 2018

This should be fixed by the Windows 10 April Update (build 1803) according to microsoft/vscode#36630.

@eryksun eryksun closed this as completed Sep 18, 2018
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OS-windows topic-IO type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants