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

Inconsistent goal output #13276

Closed
jsirois opened this issue Oct 16, 2021 · 16 comments · Fixed by #14093
Closed

Inconsistent goal output #13276

jsirois opened this issue Oct 16, 2021 · 16 comments · Fixed by #14093
Assignees
Labels

Comments

@jsirois
Copy link
Contributor

jsirois commented Oct 16, 2021

On Pants main @ 6037e69 I encountered this failure with no information about why Flake8 failed:

$ ./pants --changed-since=upstream/main fmt lint check test
10:47:55.31 [INFO] Initializing scheduler...
10:47:55.41 [INFO] Scheduler initialized.
10:47:58.52 [INFO] Completed: Building autoflake.pex from autoflake_default_lockfile.txt
10:47:58.64 [WARN] Completed: Format with Autoflake - autoflake made changes.
10:48:03.67 [INFO] Completed: Building black.pex from black_default_lockfile.txt
10:48:04.21 [WARN] Completed: Format with Black - Black made changes.
reformatted src/python/pants/engine/process_test.py
All done! ✨ 🍰 ✨
1 file reformatted, 1 file left unchanged.


10:48:07.37 [INFO] Completed: Building docformatter.pex from docformatter_default_lockfile.txt
10:48:07.48 [INFO] Completed: Format with docformatter - Docformatter made no changes.
10:48:08.47 [INFO] Completed: Building isort.pex from isort_default_lockfile.txt
10:48:08.56 [INFO] Completed: Format with isort - isort made no changes.

+ Black made changes.
✓ Docformatter made no changes.
+ autoflake made changes.
✓ isort made no changes.
10:48:08.65 [INFO] Completed: Lint with isort - isort succeeded.
10:48:08.68 [INFO] Completed: Lint with autoflake - autoflake succeeded.
10:48:08.73 [INFO] Completed: Lint with docformatter - Docformatter succeeded.
10:48:09.02 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.


10:48:11.36 [INFO] Completed: Building flake8.pex from 3rdparty/python/lockfiles/flake8.txt

✓ Black succeeded.
✓ Docformatter succeeded.
𐄂 Flake8 failed.
✓ autoflake succeeded.
✓ isort succeeded.

I re-ran and found:

$ ./pants --changed-since=upstream/main fmt lint check test
10:49:05.17 [INFO] Completed: Format with Autoflake - autoflake made no changes.
10:49:05.56 [INFO] Completed: Format with Black - Black made no changes.
All done! ✨ 🍰 ✨
2 files left unchanged.


10:49:05.56 [INFO] Completed: Format with docformatter - Docformatter made no changes.
10:49:05.56 [INFO] Completed: Format with isort - isort made no changes.

✓ Black made no changes.
✓ Docformatter made no changes.
✓ autoflake made no changes.
✓ isort made no changes.
10:49:05.57 [INFO] Completed: Lint with autoflake - autoflake succeeded.
10:49:05.57 [INFO] Completed: Lint with docformatter - Docformatter succeeded.
10:49:05.57 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.


10:49:05.57 [INFO] Completed: Lint with isort - isort succeeded.
10:49:05.77 [ERROR] Completed: Lint with Flake8 - Flake8 failed (exit code 1).
src/python/pants/engine/process.py:537:1: W293 blank line contains whitespace



✓ Black succeeded.
✓ Docformatter succeeded.
𐄂 Flake8 failed.
✓ autoflake succeeded.
✓ isort succeeded.

So the issue was src/python/pants/engine/process.py:537:1: W293 blank line contains whitespace but that was not reported on the 1st run. In the 1st run it's just reported that the flake8.pex was built 10:48:11.36 [INFO] Completed: Building flake8.pex from 3rdparty/python/lockfiles/flake8.txt, but not what the Completed: ... of that pex's execution was.

The pantsd.log shows the following for this session:

10:47:54.88 [INFO] handling request: `--changed-since=upstream/main fmt lint check test`
10:48:08.57 [INFO] notify invalidation: cleared 2 and dirtied 109 nodes for: {"src/python/pants/engine/process.py", "src/python/pants/engine"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine/process.py", "src/python/pants/engine"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine", "src/python/pants/engine/process.py"}
10:48:08.57 [INFO] notify invalidation: cleared 1 and dirtied 15 nodes for: {"src/python/pants/engine", "src/python/pants/engine/process_test.py"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine/process_test.py", "src/python/pants/engine"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine", "src/python/pants/engine/process_test.py"}
10:48:08.57 [INFO] notify invalidation: cleared 2 and dirtied 111 nodes for: {"src/python/pants/engine/process.py", "src/python/pants/engine"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine", "src/python/pants/engine/process_test.py"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine/process.py", "src/python/pants/engine"}
10:48:08.57 [INFO] Filesystem changed during run: retrying `PySnapshot` in 500ms...
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine", "src/python/pants/engine/process.py"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine", "src/python/pants/engine/process_test.py"}
10:48:08.57 [INFO] notify invalidation: cleared 0 and dirtied 0 nodes for: {"src/python/pants/engine", "src/python/pants/engine/process_test.py"}
10:48:11.56 [INFO] request completed: `--changed-since=upstream/main fmt lint check test`
10:49:04.98 [INFO] handling request: `--changed-since=upstream/main fmt lint check test`
10:49:05.77 [INFO] request completed: `--changed-since=upstream/main fmt lint check test`
10:49:15.41 [INFO] Extending leases
10:49:15.43 [INFO] Done extending leases
...
@jsirois jsirois added the bug label Oct 16, 2021
@jsirois
Copy link
Contributor Author

jsirois commented Oct 16, 2021

A third run again shows no Flake8 output. This include / exclude appears to be ~random:

$ ./pants --changed-since=upstream/main fmt lint check test
11:05:00.87 [INFO] Completed: Format with docformatter - Docformatter made no changes.
11:05:00.87 [INFO] Completed: Format with Autoflake - autoflake made no changes.
11:05:00.87 [INFO] Completed: Format with isort - isort made no changes.
11:05:00.87 [INFO] Completed: Format with Black - Black made no changes.
All done! ✨ 🍰 ✨
2 files left unchanged.



✓ Black made no changes.
✓ Docformatter made no changes.
✓ autoflake made no changes.
✓ isort made no changes.
11:05:00.87 [INFO] Completed: Lint with autoflake - autoflake succeeded.
11:05:00.87 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.


11:05:00.87 [INFO] Completed: Lint with isort - isort succeeded.
11:05:00.87 [INFO] Completed: Lint with docformatter - Docformatter succeeded.

✓ Black succeeded.
✓ Docformatter succeeded.
𐄂 Flake8 failed.
✓ autoflake succeeded.
✓ isort succeeded.

@jsirois
Copy link
Contributor Author

jsirois commented Oct 16, 2021

And again after fixing the lint, but this time in mypy:

$ ./pants --changed-since=upstream/main fmt lint check test
11:06:56.58 [INFO] Initializing scheduler...
11:06:56.72 [INFO] Scheduler initialized.
11:06:57.99 [INFO] Completed: Format with Autoflake - autoflake made no changes.
11:06:59.51 [INFO] Completed: Format with Black - Black made no changes.
All done! ✨ 🍰 ✨
2 files left unchanged.


11:07:00.72 [INFO] Completed: Format with docformatter - Docformatter made no changes.
11:07:00.80 [INFO] Completed: Format with isort - isort made no changes.

✓ Black made no changes.
✓ Docformatter made no changes.
✓ autoflake made no changes.
✓ isort made no changes.
11:07:00.88 [INFO] Completed: Lint with isort - isort succeeded.
11:07:00.90 [INFO] Completed: Lint with autoflake - autoflake succeeded.
11:07:00.92 [INFO] Completed: Lint with docformatter - Docformatter succeeded.
11:07:01.21 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.


11:07:02.04 [INFO] Completed: Lint with Flake8 - Flake8 succeeded.

✓ Black succeeded.
✓ Docformatter succeeded.
✓ Flake8 succeeded.
✓ autoflake succeeded.
✓ isort succeeded.
11:07:04.98 [INFO] Completed: Building extra_type_stubs.pex
11:07:06.94 [INFO] Completed: Building mypy.pex from mypy_default_lockfile.txt
11:07:10.08 [INFO] Completed: Installing 3rdparty/python/lockfiles/user_reqs.txt
11:07:10.48 [INFO] Completed: Extracting 13 requirements to build requirements.pex from lockfile.pex: PyYAML<5.5,>=5.4, ansicolors==1.1.8, humbug==0.2.6, ijson==3.1.4, packaging==21.0, pex==2.1.51, pytest<6.3,>=6.2.4, setuptools<5... (120 characters truncated)
11:07:11.03 [INFO] Completed: Building requirements_venv.pex

𐄂 MyPy failed.

And again:

$ ./pants --changed-since=upstream/main fmt lint check test
11:07:51.56 [INFO] Completed: Format with Black - Black made no changes.
All done! ✨ 🍰 ✨
2 files left unchanged.


11:07:51.56 [INFO] Completed: Format with Autoflake - autoflake made no changes.
11:07:51.56 [INFO] Completed: Format with isort - isort made no changes.
11:07:51.56 [INFO] Completed: Format with docformatter - Docformatter made no changes.

✓ Black made no changes.
✓ Docformatter made no changes.
✓ autoflake made no changes.
✓ isort made no changes.
11:07:51.57 [INFO] Completed: Lint with autoflake - autoflake succeeded.
11:07:51.57 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.


11:07:51.57 [INFO] Completed: Lint with docformatter - Docformatter succeeded.
11:07:51.57 [INFO] Completed: Lint with isort - isort succeeded.
11:07:51.57 [INFO] Completed: Lint with Flake8 - Flake8 succeeded.

✓ Black succeeded.
✓ Docformatter succeeded.
✓ Flake8 succeeded.
✓ autoflake succeeded.
✓ isort succeeded.

𐄂 MyPy failed.

But then fine on a 3rd try:

$ ./pants --changed-since=upstream/main fmt lint check test
11:08:21.83 [INFO] Completed: Format with Autoflake - autoflake made no changes.
11:08:21.83 [INFO] Completed: Format with isort - isort made no changes.
11:08:21.83 [INFO] Completed: Format with docformatter - Docformatter made no changes.
11:08:21.83 [INFO] Completed: Format with Black - Black made no changes.
All done! ✨ 🍰 ✨
2 files left unchanged.



✓ Black made no changes.
✓ Docformatter made no changes.
✓ autoflake made no changes.
✓ isort made no changes.
11:08:21.83 [INFO] Completed: Lint with docformatter - Docformatter succeeded.
11:08:21.83 [INFO] Completed: Lint with autoflake - autoflake succeeded.
11:08:21.83 [INFO] Completed: Lint with isort - isort succeeded.
11:08:21.83 [INFO] Completed: Lint with Flake8 - Flake8 succeeded.
11:08:21.83 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.



✓ Black succeeded.
✓ Docformatter succeeded.
✓ Flake8 succeeded.
✓ autoflake succeeded.
✓ isort succeeded.
11:08:26.33 [ERROR] Completed: Typecheck using MyPy - MyPy failed (exit code 1).
src/python/pants/engine/process_test.py: note: In function "test_find_binary_file_path":
src/python/pants/engine/process_test.py:313:78: error: Argument "search_path"
to "BinaryPathRequest" has incompatible type "List[local]"; expected
"Iterable[str]"  [arg-type]
    ... [BinaryPathRequest(binary_name=binary_name, search_path=search_path)]
                                                                ^
Found 1 error in 1 file (checked 2 source files)



𐄂 MyPy failed.

@jsirois
Copy link
Contributor Author

jsirois commented Oct 16, 2021

And one last time with test - this is very easy to repro apparently:

$ ./pants --changed-since=upstream/main fmt lint check test
11:10:10.73 [INFO] Completed: Format with Autoflake - autoflake made no changes.
11:10:11.19 [WARN] Completed: Format with Black - Black made changes.
reformatted src/python/pants/engine/process_test.py
All done! ✨ 🍰 ✨
1 file reformatted, 1 file left unchanged.


11:10:11.30 [INFO] Completed: Format with docformatter - Docformatter made no changes.
11:10:11.36 [INFO] Completed: Format with isort - isort made no changes.

+ Black made changes.
✓ Docformatter made no changes.
✓ autoflake made no changes.
✓ isort made no changes.
11:10:11.37 [INFO] Filesystem changed during run: retrying `Fmt` in 500ms...
11:10:11.95 [INFO] Completed: Lint with isort - isort succeeded.
11:10:11.98 [INFO] Completed: Lint with autoflake - autoflake succeeded.
11:10:12.00 [INFO] Completed: Lint with docformatter - Docformatter succeeded.
11:10:12.08 [INFO] Completed: Lint with Flake8 - Flake8 succeeded.
11:10:12.28 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.



✓ Black succeeded.
✓ Docformatter succeeded.
✓ Flake8 succeeded.
✓ autoflake succeeded.
✓ isort succeeded.
11:10:16.98 [INFO] Completed: Typecheck using MyPy - MyPy succeeded.
Success: no issues found in 2 source files



✓ MyPy succeeded.
11:10:22.63 [INFO] Completed: Building pytest.pex from 3rdparty/python/lockfiles/pytest.txt
11:10:22.87 [INFO] Completed: Building local_dists.pex
11:10:23.84 [INFO] Completed: Building pytest_runner.pex

𐄂 src/python/pants/engine/process_test.py:tests failed.

Fine on 2nd run though:

$ ./pants --changed-since=upstream/main fmt lint check test
11:10:40.58 [INFO] Completed: Format with Autoflake - autoflake made no changes.
11:10:40.97 [INFO] Completed: Format with Black - Black made no changes.
All done! ✨ 🍰 ✨
2 files left unchanged.


11:10:40.97 [INFO] Completed: Format with docformatter - Docformatter made no changes.
11:10:40.97 [INFO] Completed: Format with isort - isort made no changes.

✓ Black made no changes.
✓ Docformatter made no changes.
✓ autoflake made no changes.
✓ isort made no changes.
11:10:40.98 [INFO] Completed: Lint with Black - Black succeeded.
All done! ✨ 🍰 ✨
2 files would be left unchanged.


11:10:40.98 [INFO] Completed: Lint with autoflake - autoflake succeeded.
11:10:40.98 [INFO] Completed: Lint with isort - isort succeeded.
11:10:40.98 [INFO] Completed: Lint with docformatter - Docformatter succeeded.
11:10:40.98 [INFO] Completed: Lint with Flake8 - Flake8 succeeded.

✓ Black succeeded.
✓ Docformatter succeeded.
✓ Flake8 succeeded.
✓ autoflake succeeded.
✓ isort succeeded.
11:10:41.04 [INFO] Completed: Typecheck using MyPy - MyPy succeeded.
Success: no issues found in 2 source files



✓ MyPy succeeded.
11:10:42.03 [ERROR] Completed: Run Pytest - src/python/pants/engine/process_test.py:tests failed (exit code 1).
============================= test session starts ==============================
collected 16 items

src/python/pants/engine/process_test.py ...............F                 [100%]

=================================== FAILURES ===================================
__________________________ test_find_binary_file_path __________________________

rule_runner = RuleRunner(build_root=/tmp/_BUILD_ROOTl3ikv17s)
tmpdir = local('/tmp/pytest-of-jsirois/pytest-1/test_find_binary_file_path0')

    def test_find_binary_file_path(rule_runner: RuleRunner, tmpdir: py.path.local) -> None:
        binary_name = "mybin"
        binary_path_abs = tmpdir / "bin" / binary_name
        binary_path_abs.write("", ensure=True)
        binary_path_abs.chmod(0o755)
    
        binary_paths = rule_runner.request(
            BinaryPaths,
            [BinaryPathRequest(binary_name=binary_name, search_path=[binary_path_abs.strpath])],
        )
>       assert binary_paths.first_path is not None
E       AssertionError: assert None is not None
E        +  where None = BinaryPaths(binary_name='mybin', paths=()).first_path

src/python/pants/engine/process_test.py:315: AssertionError
- generated xml file: /tmp/process-executionHDL5Ut/src.python.pants.engine.process_test.py.tests.xml -
=========================== short test summary info ============================
FAILED src/python/pants/engine/process_test.py::test_find_binary_file_path - ...
========================= 1 failed, 15 passed in 0.75s =========================



𐄂 src/python/pants/engine/process_test.py:tests failed.

@benjyw
Copy link
Contributor

benjyw commented Oct 18, 2021

This is mildly terrifying. I've never experienced it (or at least noticed it) but getting to the bottom of this seems important.

Maybe this manifests more on linux than macos.

@jsirois
Copy link
Contributor Author

jsirois commented Oct 18, 2021

I got a new laptop finally and it has 16 cores, etc. This only started happening since the switch to the new laptop which is just ~1 week so it could be smoking out racy stuff better.

@benjyw
Copy link
Contributor

benjyw commented Oct 18, 2021

Ah, that seems significant. Yes, probably there is a race that your new machine is exposing. Which puts a debugging burden on you alas.

@stuhood
Copy link
Member

stuhood commented Oct 20, 2021

This is probably #11626, but it sounds like you have an excellent environment to reproduce it in. Very interested in getting to the bottom of it.

In the first example in the description, the expectation was that the workunit for the @rule running flake8 should have triggered this logging as it completed. The fact that it didn't render at either INFO or WARN makes me wonder whether the completion event didn't arrive. Inspecting captures of particular runs in Toolchain might be useful, as they will contain the complete record of workunits.

@stuhood stuhood self-assigned this Nov 3, 2021
@stuhood
Copy link
Member

stuhood commented Nov 3, 2021

@jsirois : based on the data you reported out-of-band, my best hypothesis is that this is due to these lines:

// And another to propagate stderr, which will exit automatically when the channel closes.
let _stderr_task = executor.spawn_blocking(move || {
while let Ok(stderr) = stderr_receiver.recv() {
match first_bar.upgrade() {
Some(first_bar) => first_bar.println(stderr),
None => break,
}
}
});
accepting stderr off the channel after the UI is already torn down.

These easiest path forward would be for you to confirm in your environment that that is what is happening. To do that, I'd recommend adding something like:

diff --git a/src/rust/engine/ui/src/console_ui.rs b/src/rust/engine/ui/src/console_ui.rs
index edec069808..b5d27c2577 100644
--- a/src/rust/engine/ui/src/console_ui.rs
+++ b/src/rust/engine/ui/src/console_ui.rs
@@ -119,7 +119,10 @@ impl ConsoleUI {
       while let Ok(stderr) = stderr_receiver.recv() {
         match first_bar.upgrade() {
           Some(first_bar) => first_bar.println(stderr),
-          None => break,
+          None => {
+            logging::debug_log!("repro.log", "Dropped: {:?}", stderr);
+            break;
+          }
         }
       }
     });

If that isn't what is happening, then my next guess would be that first_bar.println() can silently fail if the UI is already torn down (which might be possible, since it doesn't return an error?).

Regardless though, the solution for either issue will likely be to fix the synchronization of teardown.

@jsirois
Copy link
Contributor Author

jsirois commented Nov 14, 2021

Ok, finally got around to this. That is what's happening. Every console ui dropped output run the repro.log gets created and logged to.

@stuhood
Copy link
Member

stuhood commented Nov 15, 2021

Great! I'm not sure what the priority of #13481 will be (and it will likely need the same fix, afaict).

Do you want to take a stab at fixing this, or should I? Would likely be after Thanksgiving on my end.

@jsirois
Copy link
Contributor Author

jsirois commented Nov 15, 2021

It will also likely be after Thanksgiving on my end. If you remain assigned I'll assume you're on it since in-progress is now gone. Otheriwse, just remove your assignment and then when you or I have time we can re-self-assign.

@stuhood stuhood removed their assignment Nov 15, 2021
@stuhood
Copy link
Member

stuhood commented Jan 5, 2022

@jsirois: I'll likely pick this up as a broken window this week, since it seems like you're poking at #13899. If you want to trade (since you have a repro for this one) please let me know.

@stuhood
Copy link
Member

stuhood commented Jan 6, 2022

@jsirois : #14093 should fix this, but it would be great if you could confirm that before we land it.

EDIT: On second thought, I'll go ahead and land it, since I'd like it to bake a bit before we bother cherry-picking it. But I'll wait until you've confirmed a fix before cherry-picking.

stuhood added a commit that referenced this issue Jan 6, 2022
As described in #13276 and #11626, a race condition can occur between releasing exclusive access to the Console and the dynamic UI shutting down. In #13276, the issue was triaged to a task accepting output without confirming that the UI was still valid, and then dropping it if the UI was no longer valid.

To fix this, replace the extra task and channel (which could not be used "transactionally" to both accept stderr and validate that the UI was still valid), with an anonymous `Mutex` directly around the stderr destination.

Fixes #13276 and #11626.

[ci skip-build-wheels]
@jsirois
Copy link
Contributor Author

jsirois commented Jan 7, 2022

@stuhood this appears to fix things, but it also appears to be the case that 2 fixes are in play and I only see one: namely, I never see evidence of a failur to upgrade the weak progress bar in order to log stderr - there is never the expected log::warn fallback / retry you'd expect in that case; so is there a reason you can see that the change would solve the timing in progress bar teardown directly? Or maybe have my odds at seeing this rare event just got alot worse? I tried ~20 times before your change and after getting 2/20 fail before, 0/20 after. The before was using the commit just before your change and the 2/20 was already subjectively much better than the OP where the failure rate was maybe 3/5.

@stuhood
Copy link
Member

stuhood commented Jan 7, 2022

Thanks, you're right that we've fixed one out of two issues. Replied on #14093.

@stuhood stuhood reopened this Jan 7, 2022
@stuhood
Copy link
Member

stuhood commented Jan 7, 2022

Given that @jsirois can no longer repro, I'm going to re-resolve this, and have opened #14112 for the second issue. If we haven't seen any deadlocks in a week or so with #14093, I'll cherry-pick it to 2.8.x and 2.9.x.

@stuhood stuhood closed this as completed Jan 7, 2022
stuhood added a commit to stuhood/pants that referenced this issue Mar 3, 2022
As described in pantsbuild#13276 and pantsbuild#11626, a race condition can occur between releasing exclusive access to the Console and the dynamic UI shutting down. In pantsbuild#13276, the issue was triaged to a task accepting output without confirming that the UI was still valid, and then dropping it if the UI was no longer valid.

To fix this, replace the extra task and channel (which could not be used "transactionally" to both accept stderr and validate that the UI was still valid), with an anonymous `Mutex` directly around the stderr destination.

Fixes pantsbuild#13276 and pantsbuild#11626.

[ci skip-build-wheels]
stuhood added a commit that referenced this issue Mar 3, 2022
…4690)

As described in #13276 and #11626, a race condition can occur between releasing exclusive access to the Console and the dynamic UI shutting down. In #13276, the issue was triaged to a task accepting output without confirming that the UI was still valid, and then dropping it if the UI was no longer valid.

To fix this, replace the extra task and channel (which could not be used "transactionally" to both accept stderr and validate that the UI was still valid), with an anonymous `Mutex` directly around the stderr destination.

Fixes #13276 and #11626.

[ci skip-build-wheels]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants