Patchwork [3,of,3] py3: enable legacy stdio mode in exewrapper

mail settings
Submitter Matt Harbison
Date Dec. 17, 2018, 6:58 a.m.
Message ID <e30dd3309facf82f5306.1545029886@Envy>
Download mbox | patch
Permalink /patch/37215/
State Accepted
Headers show


Matt Harbison - Dec. 17, 2018, 6:58 a.m.
# HG changeset patch
# User Matt Harbison <>
# Date 1545000165 18000
#      Sun Dec 16 17:42:45 2018 -0500
# Node ID e30dd3309facf82f53068bcd3098cd55815a6aaf
# Parent  8b4f610c06528a66f6cd437aee1fd97f5dcea066
py3: enable legacy stdio mode in exewrapper

This drops the test failure count from 166 to 117.  The failures were typically
in the form of `hg serve -d` spawning but crashing immediately, leaving clients
with "bad http status" lines, connection refusals, and so forth.  The underlying
message on the server side was either "OSError: [WinError 6] The handle is
invalid" or "OSError: [WinError 1] Incorrect function". Additionally, no output
was rendered if the pager was activated.  Thanks to Yuya for diagnosing the

The failure count drops to 107 when PYTHONLEGACYWINDOWSSTDIO=1 is defined in the
environment.  These failures seem to revolve around the dummyssh server process,
and  So I'll probably add that to the test runner.

One small regression here (only in py3) is that if hg.exe is already built, a
messagebox appears when building it again saying that python37.dll can't be
loaded.  Python3 isn't in PATH by default, and tries running bare `hg`
first.  But MSYS prepends '.' to PATH, so it runs the local hg, but can't find
the library.  It falls back to the python used to invoke, so ultimately
it works.  I'm not sure if it's better to strip '.' from PATH or just skip right
to `sys.executable hg` on Windows.

Also, something seems to be wrong with run-tests._usecorrectpython().  I
accidentially left off the 'PYTHON="py -3"' when building (thus making py2
stuff), and yet managed to invoke with "py -3".  (And that only had
67 failures.)


diff --git a/mercurial/exewrapper.c b/mercurial/exewrapper.c
--- a/mercurial/exewrapper.c
+++ b/mercurial/exewrapper.c
@@ -10,6 +10,7 @@ 
 #include <stdio.h>
 #include <tchar.h>
 #include <windows.h>
+#include <Python.h>
 #include "hgpythonlib.h"
@@ -46,6 +47,10 @@  int _tmain(int argc, TCHAR *argv[])
 	void(__cdecl * Py_SetPythonHome)(TCHAR * home);
 	int(__cdecl * Py_Main)(int argc, TCHAR *argv[]);
+	Py_LegacyWindowsStdioFlag = 1;
 	if (GetModuleFileName(NULL, pyscript, _countof(pyscript)) == 0) {
 		err = "GetModuleFileName failed";
 		goto bail;
diff --git a/tests/ b/tests/
--- a/tests/
+++ b/tests/
@@ -2640,6 +2640,10 @@  class TestRunner(object):
             self._tmpbindir = self._bindir
             self._pythondir = os.path.join(self._installdir, b"lib", b"python")
+        # Force the use of hg.exe instead of relying on MSYS to recognize hg is
+        # a python script and feed it to python.exe.  Legacy stdio is force
+        # enabled by hg.exe, and this is a more realistic way to launch hg
+        # anyway.
         if == 'nt' and not self._hgcommand.endswith(b'.exe'):
             self._hgcommand += b'.exe'