gh-110147: run console io test in new process
diff --git a/Lib/test/test_msvcrt.py b/Lib/test/test_msvcrt.py
index 81ec13026014e6..600c4446fd5cd4 100644
--- a/Lib/test/test_msvcrt.py
+++ b/Lib/test/test_msvcrt.py
@@ -1,17 +1,17 @@
 import os
+import subprocess
 import sys
 import unittest
+from textwrap import dedent
 
-from test.support import os_helper
+from test.support import os_helper, requires_resource
 from test.support.os_helper import TESTFN, TESTFN_ASCII
 
 if sys.platform != "win32":
     raise unittest.SkipTest("windows related tests")
 
 import _winapi
-import msvcrt;
-
-from _testconsole import write_input, flush_console_input_buffer
+import msvcrt
 
 
 class TestFileOperations(unittest.TestCase):
@@ -61,34 +61,45 @@ def test_get_osfhandle(self):
 
 
 class TestConsoleIO(unittest.TestCase):
+    # CREATE_NEW_CONSOLE creates a "popup" window.
+    @requires_resource('gui')
+    def run_in_separated_process(self, code):
+        # Run test in a seprated process to avoid stdin conflicts.
+        # See: gh-110147
+        cmd = [sys.executable, '-c', code]
+        subprocess.run(cmd, check=True, capture_output=True,
+                       creationflags=subprocess.CREATE_NEW_CONSOLE)
+
     def test_kbhit(self):
-        h = msvcrt.get_osfhandle(sys.stdin.fileno())
-        flush_console_input_buffer(h)
-        self.assertEqual(msvcrt.kbhit(), 0)
+        code = dedent('''
+            import msvcrt
+            assert msvcrt.kbhit() == 0
+        ''')
+        self.run_in_separated_process(code)
 
     def test_getch(self):
         msvcrt.ungetch(b'c')
         self.assertEqual(msvcrt.getch(), b'c')
 
-    def test_getwch(self):
-        with open('CONIN$', 'rb', buffering=0) as stdin:
-            h = msvcrt.get_osfhandle(stdin.fileno())
-            flush_console_input_buffer(h)
+    def check_getwch(self, funcname):
+        code = dedent(f'''
+            import msvcrt
+            from _testconsole import write_input
+            with open("CONIN$", "rb", buffering=0) as stdin:
+                write_input(stdin, {ascii(c_encoded)})
+                assert msvcrt.{funcname}() == "{c}"
+        ''')
+        self.run_in_separated_process(code)
 
-            write_input(stdin, c_encoded)
-            self.assertEqual(msvcrt.getwch(), c)
+    def test_getwch(self):
+        self.check_getwch('getwch')
 
     def test_getche(self):
         msvcrt.ungetch(b'c')
         self.assertEqual(msvcrt.getche(), b'c')
 
     def test_getwche(self):
-        with open('CONIN$', 'rb', buffering=0) as stdin:
-            h = msvcrt.get_osfhandle(stdin.fileno())
-            flush_console_input_buffer(h)
-
-            write_input(stdin, c_encoded)
-            self.assertEqual(msvcrt.getwche(), c)
+        self.check_getwch('getwche')
 
     def test_putch(self):
         msvcrt.putch(b'c')
diff --git a/PC/_testconsole.c b/PC/_testconsole.c
index 5e5a771b96bfec..1dc0d230c4d7c3 100644
--- a/PC/_testconsole.c
+++ b/PC/_testconsole.c
@@ -133,31 +133,12 @@ _testconsole_read_output_impl(PyObject *module, PyObject *file)
     Py_RETURN_NONE;
 }
 
-/*[clinic input]
-_testconsole.flush_console_input_buffer
-    handle: HANDLE
-
-Flushes the console input buffer.
-
-All input records currently in the input buffer are discarded.
-[clinic start generated code]*/
-
-static PyObject *
-_testconsole_flush_console_input_buffer_impl(PyObject *module, void *handle)
-/*[clinic end generated code: output=1f923a81331465ce input=be8203ae84a288f5]*/
-/*[clinic end generated code:]*/
-{
-    FlushConsoleInputBuffer(handle);
-
-    Py_RETURN_NONE;
-}
 
 #include "clinic\_testconsole.c.h"
 
 PyMethodDef testconsole_methods[] = {
     _TESTCONSOLE_WRITE_INPUT_METHODDEF
     _TESTCONSOLE_READ_OUTPUT_METHODDEF
-    _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF
     {NULL, NULL}
 };
 
diff --git a/PC/clinic/_testconsole.c.h b/PC/clinic/_testconsole.c.h
index b76588909782ea..99cd302ff34698 100644
--- a/PC/clinic/_testconsole.c.h
+++ b/PC/clinic/_testconsole.c.h
@@ -132,70 +132,6 @@ _testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nar
 
 #endif /* defined(MS_WINDOWS) */
 
-#if defined(MS_WINDOWS)
-
-PyDoc_STRVAR(_testconsole_flush_console_input_buffer__doc__,
-"flush_console_input_buffer($module, /, handle)\n"
-"--\n"
-"\n"
-"Flushes the console input buffer.\n"
-"\n"
-"All input records currently in the input buffer are discarded.");
-
-#define _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF    \
-    {"flush_console_input_buffer", _PyCFunction_CAST(_testconsole_flush_console_input_buffer), METH_FASTCALL|METH_KEYWORDS, _testconsole_flush_console_input_buffer__doc__},
-
-static PyObject *
-_testconsole_flush_console_input_buffer_impl(PyObject *module, void *handle);
-
-static PyObject *
-_testconsole_flush_console_input_buffer(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
-
-    #define NUM_KEYWORDS 1
-    static struct {
-        PyGC_Head _this_is_not_used;
-        PyObject_VAR_HEAD
-        PyObject *ob_item[NUM_KEYWORDS];
-    } _kwtuple = {
-        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
-        .ob_item = { &_Py_ID(handle), },
-    };
-    #undef NUM_KEYWORDS
-    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
-
-    #else  // !Py_BUILD_CORE
-    #  define KWTUPLE NULL
-    #endif  // !Py_BUILD_CORE
-
-    static const char * const _keywords[] = {"handle", NULL};
-    static _PyArg_Parser _parser = {
-        .keywords = _keywords,
-        .fname = "flush_console_input_buffer",
-        .kwtuple = KWTUPLE,
-    };
-    #undef KWTUPLE
-    PyObject *argsbuf[1];
-    void *handle;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    handle = PyLong_AsVoidPtr(args[0]);
-    if (!handle && PyErr_Occurred()) {
-        goto exit;
-    }
-    return_value = _testconsole_flush_console_input_buffer_impl(module, handle);
-
-exit:
-    return return_value;
-}
-
-#endif /* defined(MS_WINDOWS) */
-
 #ifndef _TESTCONSOLE_WRITE_INPUT_METHODDEF
     #define _TESTCONSOLE_WRITE_INPUT_METHODDEF
 #endif /* !defined(_TESTCONSOLE_WRITE_INPUT_METHODDEF) */
@@ -203,8 +139,4 @@ _testconsole_flush_console_input_buffer(PyObject *module, PyObject *const *args,
 #ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF
     #define _TESTCONSOLE_READ_OUTPUT_METHODDEF
 #endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */
-
-#ifndef _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF
-    #define _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF
-#endif /* !defined(_TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF) */
-/*[clinic end generated code: output=5d488564f2500dd9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=f59fe72cd4e73704 input=a9049054013a1b77]*/

<!--
Thanks for your contribution!
Please read this comment in its entirety. It's quite important.

# Pull Request title

It should be in the following format:

```
gh-NNNNN: Summary of the changes made
```

Where: gh-NNNNN refers to the GitHub issue number.

Most PRs will require an issue number. Trivial changes, like fixing a typo, do not need an issue.

# Backport Pull Request title

If this is a backport PR (PR made against branches other than `main`),
please ensure that the PR title is in the following format:

```
[X.Y] <title from the original PR> (GH-NNNN)
```

Where: [X.Y] is the branch name, e.g. [3.6].

GH-NNNN refers to the PR number from `main`.

-->


<!-- gh-issue-number: gh-110147 -->
* Issue: gh-110147
<!-- /gh-issue-number -->
