We need to do something about these feature tests #15294

Open
opened 2026-01-31 04:34:04 +00:00 by claunia · 5 comments
Owner

Originally created by @zadjii-msft on GitHub (Sep 20, 2021).

Seriously. I'd reckon that 50% of our CI runs fail due to this. Dunno what happened to make these flakier. EIM seems like a good time to address this.

Previous notes:

We're definitely correctly waiting on the conhost / openconsole process to start. It's just that some percent of the time, it still just fails to re-open the stdout handle and attach to that console. Crazy.

Originally created by @zadjii-msft on GitHub (Sep 20, 2021). Seriously. I'd reckon that 50% of our CI runs fail due to this. Dunno what happened to make these flakier. EIM seems like a good time to address this. Previous notes: * #11858 * #8534 * #15106 We're definitely correctly waiting on the conhost / openconsole process to start. It's just that some percent of the time, it still just fails to re-open the stdout handle and attach to that console. Crazy.
claunia added the Issue-TaskProduct-MetaArea-Build labels 2026-01-31 04:34:04 +00:00
Author
Owner

@tusharsnx commented on GitHub (Aug 27, 2023):

I spend some time digging into this.

We're definitely correctly waiting on the conhost / openconsole process to start.

I can confirm this. Every call to freopen_s is reaching the newly spawned openconsole properly. It invokes two calls inside openconsole, first CONSOLE_IO_CLOSE_OBJECT and then CONSOLE_IO_CREATE_OBJECT inside IoSorter.cpp.

@zadjii-msft We can't see what raw ioctl reply is received by the application, can we? I'm assuming this is implemented within ConsoleApi*.h which is not part of this repository.

@tusharsnx commented on GitHub (Aug 27, 2023): I spend some time digging into this. > We're definitely correctly waiting on the conhost / openconsole process to start. I can confirm this. Every call to `freopen_s` is reaching the newly spawned `openconsole` properly. It invokes two calls inside openconsole, first `CONSOLE_IO_CLOSE_OBJECT` and then `CONSOLE_IO_CREATE_OBJECT` inside `IoSorter.cpp`. @zadjii-msft We can't see what raw ioctl reply is received by the application, can we? I'm assuming this is implemented within `ConsoleApi*.h` which is not part of this repository.
Author
Owner

@tusharsnx commented on GitHub (Aug 27, 2023):

More details:

Even the first call to freopen_s within the sleep (for) loop makes it to the newly spawned console, which indicate that sleep shouldn't be required for 'wait for console to get ready'.

It just that the new handles that were created/returned by the conhost are sometimes valid, sometimes not, and sometimes never even after trying several times. Seems like a magic so far 🤔.

Removing these lines is enough to stop tests from failing 100% of the time out of my 30 min of testing it with 'run until failure' (though I now don't know how to stop a test that passes all the time 😂, had to close VS)

821ae3af2d/src/host/ft_host/InitTests.cpp (L256-L259)

We could get rid of the whole sleep loop, since I tested with/without it and it worked regardless.

This led me to believe that our ObjectHandleData create/destroy is busted somewhere, surety level: negative.

If someone could confirm these, I'd be happy to raise a PR proposing these changes.

@tusharsnx commented on GitHub (Aug 27, 2023): More details: Even the first call to `freopen_s` within the sleep (for) loop makes it to the newly spawned console, which indicate that sleep shouldn't be required for 'wait for console to get ready'. It just that the new handles that were created/returned by the conhost are sometimes valid, sometimes not, and sometimes never even after trying several times. Seems like a magic so far 🤔. Removing these lines is enough to stop tests from failing 100% of the time out of my 30 min of testing it with 'run until failure' (though I now don't know how to stop a test that passes all the time 😂, had to close VS) https://github.com/microsoft/terminal/blob/821ae3af2d311350fbfaa4c77af09858488681e9/src/host/ft_host/InitTests.cpp#L256-L259 *We could get rid of the whole sleep loop, since I tested with/without it and it worked regardless.* This led me to believe that our `ObjectHandleData` create/destroy is busted somewhere, surety level: negative. If someone could confirm these, I'd be happy to raise a PR proposing these changes.
Author
Owner

@lhecker commented on GitHub (Aug 28, 2023):

We could get rid of the whole sleep loop, since I tested with/without it and it worked regardless.

Nice finding!

Getting rid of the freopen_s will be hard, because we use the CRT printing functions (like printf) in some tests. IMO we could just remove those tests because they test the CRT's and not conhost's correctness.
Alternatively, we could use _open_osfhandle and _fdopen to turn the new console handles into new FILE* handles without the need to close or reopen the old ones.

@lhecker commented on GitHub (Aug 28, 2023): > We could get rid of the whole sleep loop, since I tested with/without it and it worked regardless. Nice finding! Getting rid of the `freopen_s` will be hard, because we use the CRT printing functions (like `printf`) in some tests. IMO we could just remove those tests because they test the CRT's and not conhost's correctness. Alternatively, we could use `_open_osfhandle` and `_fdopen` to turn the new console handles into new `FILE*` handles without the need to close or reopen the old ones.
Author
Owner

@tusharsnx commented on GitHub (Aug 28, 2023):

One more thing. A huge one.

The testhost surprisingly is not a console app, so the new handle that is created is not set as a standard input/output handle by ucrt, and is not a standard handle. Whatever GetStdHandle returns is old and very well a wrong handle. I'm sure we didn't expect that 😅.

We can easily workaround that by doing SetStdHandle(STD_INPUT_HANDLE, _get_osfhandle(_fileno(stdin)))

Getting rid of the freopen_s will be hard, because we use the CRT printing functions (like printf) in some tests.

Didn't notice that, thanks for the heads up. 👍

@tusharsnx commented on GitHub (Aug 28, 2023): One more thing. A huge one. The testhost surprisingly is *not a console app*, so the new handle that is created is not set as a standard input/output handle by ucrt, and is not a standard handle. Whatever GetStdHandle returns is old and very well a wrong handle. I'm sure we didn't expect that 😅. We can easily workaround that by doing `SetStdHandle(STD_INPUT_HANDLE, _get_osfhandle(_fileno(stdin)))` > Getting rid of the freopen_s will be hard, because we use the CRT printing functions (like printf) in some tests. Didn't notice that, thanks for the heads up. 👍
Author
Owner

@tusharsnx commented on GitHub (Aug 29, 2023):

Just to give an idea, here is where it checks if SetStdHandle needs to be called for the new handle.

In ucrt/lowio/osfinfo.cpp:

Screenshot 2023-08-28 181335

_query_app_type() returns _crt_app_unknown and skips the if body.

@tusharsnx commented on GitHub (Aug 29, 2023): Just to give an idea, here is where it checks if SetStdHandle needs to be called for the new handle. In `ucrt/lowio/osfinfo.cpp`: ![Screenshot 2023-08-28 181335](https://github.com/microsoft/terminal/assets/55626797/ac152e96-4a59-4fbc-b6a1-476878e6dc29) `_query_app_type()` returns `_crt_app_unknown` and skips the `if` body.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#15294