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

Thread-local stdio handling to support concurrent pantsd clients #11536

Merged

Conversation

stuhood
Copy link
Member

@stuhood stuhood commented Feb 9, 2021

Problem

In order to support concurrent pantsd clients, work spawned by each client (even into background threads) must interact with the relevant stdio file handles. And when a client disconnects, spawned work should be able to continue to log to the pantsd.log.

Solution

Extract the thread/task-local aspects of our logging crate into a stdio crate that provides:

  1. a Console-aware logging destination
  2. exclusive access to a Console while a UI or InteractiveProcess is running
  3. Python-level sys.std* replacements

Result

No user-visible impact, but one of the largest remaining blockers for #7654 is removed.

@stuhood stuhood force-pushed the stuhood/threadlocal-io-destinations branch 3 times, most recently from 4219cdc to cc6eb14 Compare February 10, 2021 21:31
@stuhood stuhood force-pushed the stuhood/threadlocal-io-destinations branch 3 times, most recently from 53cf8e9 to cd21f44 Compare February 18, 2021 20:11
stuhood added a commit that referenced this pull request Feb 22, 2021
### Problem

#11536 moves from using POSIX-level replacement of the `stdio` file descriptors `{0, 1, 2}`, to replacing `sys.std*` with a thread-local implementation. Unfortunately, Python `subprocess`/`Popen` APIs hardcode `{0, 1, 2}` rather than actually inspecting `sys.std*.fileno()`, and so usages of those APIs that use `std*=None` (i.e. "inherit" mode), will inherit intentionally dead/closed file handles under `pantsd`.

PEX uses inherit mode when spawning `pip` (in order to pass through `stderr` to the parent process), and this runs afoul of the above behavior. Pants has used PEX as a library for a very long time, but 95% of usecases have now migrated to using PEX as a binary, with wrappers exposed via the `@rule` API. The `PluginResolver` that Pants uses to resolve its own code is the last usage of PEX as a library. 

### Solution

In a series of commits, introduce a "bootstrap" `Scheduler` that is able to resolve plugins after an `OptionsBootstrapper` has been created, but before creating the `BuildConfiguration` (which contains plugin information).

### Result

Although Pants has some stray references to PEX APIs, it no longer uses PEX as a library to resolve dependencies. #11536 and #7654 are unblocked.

In future, if the options required to construct a minimal scheduler can be further pruned, the bootstrap `Scheduler` might also be able to be used to create the `OptionsBootstrapper`, which would allow for addressing #10360.
@stuhood stuhood force-pushed the stuhood/threadlocal-io-destinations branch from cd21f44 to f07797f Compare February 24, 2021 01:00
…ate, and implement stdio replacement in Rust.

[ci skip-build-wheels]
@stuhood stuhood force-pushed the stuhood/threadlocal-io-destinations branch from f07797f to d129bed Compare February 25, 2021 00:24
@stuhood stuhood requested review from gshuflin, Eric-Arellano, jsirois and tdyas and removed request for gshuflin February 25, 2021 01:10
@stuhood stuhood marked this pull request as ready for review February 25, 2021 01:11
@stuhood
Copy link
Member Author

stuhood commented Feb 25, 2021

Hey folks: this is ready for review. Sorry for the huge commit.

@Eric-Arellano
Copy link
Contributor

Hey folks: this is ready for review. Sorry for the huge commit.

Any tips for it, like read this file first? Or things you want us to look out for?

@@ -147,3 +151,5 @@ env_logger = "0.5.4"
prost = { git = "https://github.com/danburkert/prost", rev = "a1cccbcee343e2c444e1cd2738c7fba2599fc391" }
prost-build = { git = "https://github.com/danburkert/prost", rev = "a1cccbcee343e2c444e1cd2738c7fba2599fc391" }
prost-types = { git = "https://github.com/danburkert/prost", rev = "a1cccbcee343e2c444e1cd2738c7fba2599fc391" }
# TODO: Stabilize before landing.
console = { git = "https://github.com/stuhood/console", branch = "stuhood/term-target-for-arbitrary-handles" }
Copy link
Contributor

@gshuflin gshuflin Feb 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So right now we're relying on some changes you made in your own copy of this repo?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I'll fork them to pantsbuild/pants before landing.

Copy link
Contributor

@jsirois jsirois left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

It would be good to address the ~2 TODOs or file.

src/rust/engine/stdio/src/lib.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@Eric-Arellano Eric-Arellano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Epic!

src/python/pants/core/goals/repl_integration_test.py Outdated Show resolved Hide resolved
src/python/pants/core/goals/repl_integration_test.py Outdated Show resolved Hide resolved
src/python/pants/core/goals/repl_integration_test.py Outdated Show resolved Hide resolved
src/python/pants/core/goals/run_test.py Outdated Show resolved Hide resolved
src/python/pants/init/logging.py Outdated Show resolved Hide resolved
src/python/pants/init/logging.py Outdated Show resolved Hide resolved
src/python/pants/init/logging.py Outdated Show resolved Hide resolved
src/rust/engine/stdio/src/lib.rs Show resolved Hide resolved
src/rust/engine/stdio/src/lib.rs Outdated Show resolved Hide resolved
@stuhood stuhood force-pushed the stuhood/threadlocal-io-destinations branch from cc7c446 to a5af6f4 Compare March 1, 2021 20:28

///
/// If stdout is backed by a real file, returns it as a RawFd. All usage of `RawFd` is unsafe,
/// but this method is additionally unsafe because the real file might have been closed by the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is kind of confusing, since this method is not marked as a Rust unsafe function. IIRC the libc functions that manipulate RawFd are generally unsafe, but that's not the same thing as this function that generates RawFd being unsafe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unsafety here is technically just the same unsafety that is possible for any RawFd... this function will not directly panic: instead, the RawFd that you get might already be closed. So the comment is probably misleading, yea.

[ci skip-build-wheels]
@stuhood stuhood force-pushed the stuhood/threadlocal-io-destinations branch from a5af6f4 to 4078b32 Compare March 1, 2021 23:06
@stuhood stuhood merged commit 87f2261 into pantsbuild:master Mar 1, 2021
@stuhood stuhood deleted the stuhood/threadlocal-io-destinations branch March 1, 2021 23:53
@stuhood
Copy link
Member Author

stuhood commented Mar 1, 2021

This was green aside from some flakes in Github Actions for macOS: opened #11617 for those.

stuhood added a commit that referenced this pull request Mar 4, 2021
### Problem

A few references to the deprecated `.pants.d/pantsd/pantsd.log` location survived after #11536.

### Solution

Fixup the references to point to the new location at `.pants.d/pants.log`.

[ci skip-rust]
[ci skip-build-wheels]
stuhood added a commit that referenced this pull request Mar 11, 2021
### Problem

Since migrating to thread-local `stdio` in #11536, explicit stdio rendering methods on `Session`/`Scheduler` have been dead code. But additionally, our UI fallback could hypothetically have been interacting with `std::io::std*` on fds `1,2`, which would cause a crash.

### Solution

Remove some dead (and some dangerous!) code around stdio in `Scheduler`/`Session`, and isolate stderr handling to the UI crate.

### Result

Probably fixes #11626.

[ci skip-build-wheels]
stuhood added a commit that referenced this pull request Mar 16, 2021
…`. (#11703)

### Problem

The threadlocal implementation of `sys.stdin` added in #11536 did not expose enough methods to be used for `input`.

### Solution

Implement the methods needed for `input`, and wrap for use buffered text consumption.

### Result

Fixes #11398.

[ci skip-build-wheels]
stuhood added a commit that referenced this pull request Mar 18, 2021
…t. (#11731)

### Problem

`pantsd` has closed the file handles associated with `sys.std*` (fds "0, 1, 2") since its early inception, and until #11536 it allowed exactly one client at a time in order to redirect those precise fd numbers to the client socket (via nailgun).

It's likely that:
1. before #11536, between the closing of stdio and its replacement when a client connected, any attempt to interact with `sys.std*` or Rust's stdio file handles would crash.
2. after #11536, interactions with `sys.std*` or Rust's stdio file handles at _any_ time would crash.

### Solution

Rather than closing `sys.std*` in `pantsd`, replace them with valid file handles as a backstop against code that has-not/cannot be updated to avoid touching them (such as Rust panic handlers). In the case of `stdout`/`stderr`, redirect them to append to the `pants.log`.

### Result

Given what was reported on tokio-rs/tokio#3499, it's likely that this fixes #11364 by replacing the "panicked while processing panic" message with an actual panic message rendered in the `pants.log` (for which we can open a new ticket). 

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

Successfully merging this pull request may close these issues.

5 participants