Skip to content

Commit 496acaa

Browse files
committed
Handle multiple encodings for WSL error messages
This affects the test suite only. It improves _WinBashStatus. When bash.exe is the WSL wrapper, and it reports an error that prevents bash in a WSL system from ever actually being run, the message may be encoded in a narrow or multibyte encoding, or may instead be in Windows's native UTF-16LE encoding. This was partly handled before, by assuming the message indicating the absence of any installed WSL distribuions could be interpreted as UTF-8, but matching against bytes and not actually decoding it or other error messages. That presented a few problems, which are rememedied here: - It turns out that this "Windows Subsystem for Linux has no installed distributions" message actually can be in UTF-16LE too. This happens when it is part of a message that also reports a textual error code like: Bash/Service/CreateInstance/GetDefaultDistro/WSL_E_DEFAULT_DISTRO_NOT_FOUND Therefore, narrow-encoding matching was not sufficient. - Logged messages were hard to understand, because they were printing the reprs of bytes objects, which sometimes were UTF-16LE and thus had many "\x00" interspersed in them. - The cases were not broken down elegantly. The ErrorWhileChecking case could hold a CompletedProcess, a CalledProcessError, or an OSError. This is now replaced with a WinError case for the rare scenario where CreateProcessW fails in a completely unexpected way, and a CheckError case for when the exit status or output of bash.exe indicates an error other than one we want to handle. CheckError has two attributes: `process` for the CompletedProcess (CalledProcessError is no longer used, and CompletedProcess has `returncode` and other attributes that provide the same info), and `message` for the decoded output.
1 parent d5ed266 commit 496acaa

File tree

1 file changed

+20
-24
lines changed

1 file changed

+20
-24
lines changed

test/test_index.py

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,11 @@ class _WinBashStatus:
6161
WslNoDistro = constructor()
6262
"""Running ``bash.exe` tries to run bash on a WSL distribution, but none exists."""
6363

64-
ErrorWhileChecking = constructor("error_or_process")
65-
"""Could not determine the status.
64+
CheckError = constructor("process", "message")
65+
"""Running ``bash.exe`` fails in an unexpected error or gives unexpected output."""
6666

67-
This should not trigger a skip or xfail, as it typically indicates either a fixable
68-
problem on the test machine, such as an "Insufficient system resources exist to
69-
complete the requested service" error starting WSL, or a bug in this detection code.
70-
"""
67+
WinError = constructor("exception")
68+
"""``bash.exe`` may exist but can't run. ``CreateProcessW`` fails unexpectedly."""
7169

7270
@classmethod
7371
def check(cls):
@@ -94,36 +92,34 @@ def check(cls):
9492
if os.name != "nt":
9593
return cls.Inapplicable()
9694

97-
# Use bytes because messages for different WSL errors use different encodings.
98-
no_distro_message = b"Windows Subsystem for Linux has no installed distributions."
99-
100-
def error_running_bash(error):
101-
log.error("Error running bash.exe to check WSL status: %r", error)
102-
return cls.ErrorWhileChecking(error)
95+
no_distro_message = "Windows Subsystem for Linux has no installed distributions."
10396

10497
try:
10598
# Output rather than forwarding the test command's exit status so that if a
10699
# failure occurs before we even get to this point, we will detect it. For
107100
# information on ways to check for WSL, see https://superuser.com/a/1749811.
108101
script = 'test -e /proc/sys/fs/binfmt_misc/WSLInterop; echo "$?"'
109102
command = ["bash.exe", "-c", script]
110-
proc = subprocess.run(command, capture_output=True, check=True)
103+
process = subprocess.run(command, capture_output=True)
111104
except FileNotFoundError:
112105
return cls.Absent()
113106
except OSError as error:
114-
return error_running_bash(error)
115-
except subprocess.CalledProcessError as error:
116-
if error.returncode == 1 and error.stdout.startswith(no_distro_message):
117-
return cls.WslNoDistro()
118-
return error_running_bash(error)
119-
120-
status = proc.stdout.rstrip()
121-
if status == b"0":
107+
return cls.WinError(error)
108+
109+
encoding = "utf-16le" if b"\r\0\n\0" in process.stdout else "utf-8"
110+
text = process.stdout.decode(encoding).rstrip() # stdout includes WSL errors.
111+
112+
if process.returncode == 1 and text.startswith(no_distro_message):
113+
return cls.WslNoDistro()
114+
if process.returncode != 0:
115+
log.error("Error running bash.exe to check WSL status: %s", text)
116+
return cls.CheckError(process, text)
117+
if text == "0":
122118
return cls.Wsl()
123-
if status == b"1":
119+
if text == "1":
124120
return cls.Native()
125-
log.error("Strange output checking WSL status: %r", proc.stdout)
126-
return cls.ErrorWhileChecking(proc)
121+
log.error("Strange output checking WSL status: %s", text)
122+
return cls.CheckError(process, text)
127123

128124

129125
_win_bash_status = _WinBashStatus.check()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy