Skip to content

Comments

Don't panic on Ctrl-C in confirm prompt#11706

Merged
konstin merged 3 commits intoastral-sh:mainfrom
ericmarkmartin:ctrl-c-panicking
Feb 26, 2025
Merged

Don't panic on Ctrl-C in confirm prompt#11706
konstin merged 3 commits intoastral-sh:mainfrom
ericmarkmartin:ctrl-c-panicking

Conversation

@ericmarkmartin
Copy link
Contributor

@ericmarkmartin ericmarkmartin commented Feb 22, 2025

Summary

Resolves #11704

Propagate errors from uv_console::confirm up instead of unwrapping them, causing panics.

Test Plan

Regression testing the bug is very difficult, as the behavior of confirm changes based on whether uv is talking to a tty. We can trick it using ptys, but the best rust pty crate I could find only provides blocking reads of the spawned child, which is insufficient to write the regression test.

@ericmarkmartin
Copy link
Contributor Author

Took a brief stab at testing, but failed. Not sure how to test the behavior when we need the subprocess to be interactive in order to see the confirmation prompt. For reference, this is what I attempted to no avail (the snapshot looks like what happens if you answer the confirmation prompt with no).

#[test]
fn ctrl_c_install_confirmation_prompt() -> Result<()> {
    let context = TestContext::new("3.12");

    context.temp_dir.child("pyproject.toml").touch()?;

    let ctrl_c_file = context.temp_dir.child("ctrl_c");

    ctrl_c_file.write_binary(&[0x03])?;

    let file_handle = std::fs::File::open(ctrl_c_file)?;

    uv_snapshot!(context.filters(), context.pip_install()
        .arg("pyproject.toml") // triggers confirmation prompt because user probably wants `-r`
        .stdin(file_handle), @r###"
        "###
    );

    Ok(())
}

Copy link
Contributor Author

@ericmarkmartin ericmarkmartin left a comment

Choose a reason for hiding this comment

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

I've added a test that seems to work using pty, which I get out of wezterm's pty implementation. One thing to note is that the read out of the pty is non-blocking so if our confirmation prompt changes and becomes smaller, the test will hang, which isn't great. Still thinking of ways to fix that.

Part of making the test workable was a drive-by change so that the confirmation prompt respects the global color setting

@ericmarkmartin ericmarkmartin marked this pull request as draft February 24, 2025 03:29
@ericmarkmartin
Copy link
Contributor Author

Apparently the fix doesn't work on windows, so converting back to draft while I workshop a bit

@konstin
Copy link
Member

konstin commented Feb 24, 2025

Can you try forwarding the io error? The handler seems working, but i think the main thread panics too fast.

@ericmarkmartin
Copy link
Contributor Author

Can you try forwarding the io error? The handler seems working, but i think the main thread panics too fast.

Forwarding it out of where? I think the main thread panics because we forward it out of the confirm function and unwrap the containing Result, no?

@konstin
Copy link
Member

konstin commented Feb 25, 2025

Besides the behavior changes to signal handling, we would ideally not have an .unwrap() call at all, usually we can just propagate the error to the caller through a thiserror derive enum variant.

@ericmarkmartin
Copy link
Contributor Author

Ah okay, that makes sense. I've rolled back the signal handling changes because it requires some changes to the console crate's windows implementation, which I'll try to PR separately but it probably shouldn't block this.

Do you have thoughts on adding back the test with the pseudoterminal? My inclination is that it's not worth it given it's proclivity to hanging

@ericmarkmartin
Copy link
Contributor Author

which I'll try to PR separately

see console-rs/console#235

@ericmarkmartin ericmarkmartin marked this pull request as ready for review February 26, 2025 06:36
@konstin
Copy link
Member

konstin commented Feb 26, 2025

Thanks for making the upstream PR!

I think it is fine this way, it's clear the panic cannot occur anymore given that the unwrap() is gone.

I've changed the error handling in uv/src/lib.rs to forward the io::Error if one occurs.

@konstin konstin added the bug Something isn't working label Feb 26, 2025
@konstin konstin changed the title handle Ctrl-C explicitly in confirm prompt Don't panic on Ctrl-C in confirm prompt Feb 26, 2025
@konstin konstin merged commit 6e7ec32 into astral-sh:main Feb 26, 2025
74 checks passed
@ericmarkmartin ericmarkmartin deleted the ctrl-c-panicking branch February 27, 2025 02:33
loic-lescoat pushed a commit to loic-lescoat/uv that referenced this pull request Mar 2, 2025
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
Resolves astral-sh#11704 

Propagate errors from `uv_console::confirm` up instead of `unwrap`ping
them, causing panics.

## Test Plan

<!-- How was it tested? -->
Regression testing the bug is very difficult, as the behavior of
`confirm` changes based on whether `uv` is talking to a `tty`. We can
trick it using ptys, but the best rust pty crate I could find only
provides blocking reads of the spawned child, which is insufficient to
write the regression test.

---------

Co-authored-by: konstin <[email protected]>
charliermarsh pushed a commit that referenced this pull request Mar 3, 2025
…dler (#11897)

<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Follow on to #11706. In the original PR, I tried to solve the issue by
getting rid of the `ctrlc::set_handler` call. Unfortunately, this didn't
work on windows due to an issue with the console crate. console 0.15.11
includes console-rs/console#235, which resolves
the issue, so now we can get rid of the call.

<!-- What's the purpose of the change? What does it do, and why? -->

This change is not super important but I still think it's worthwhile.
For one, spinning up a background thread to handle `SIGINT`s when we're
going to be raising the `SIGINT` from within the function is more
technical complexity than needed, now that there's an easy way to
explicitly catch the Ctrl-C from the terminal input. Secondly,
`ctrlc::set_handler`'s
[docs](https://docs.rs/ctrlc/3.4.5/ctrlc/fn.set_handler.html) advise
that you set the handler just once, at the beginning of the program, so
this use seems somewhat error prone. In fact, uv already has a second
[callsite](https://github.com/astral-sh/uv/blob/461f4d9007160f7061a4fc0c4a5a84c613fdbff7/crates/uv/src/commands/project/add.rs#L596-L611)
for this function (though I'm not sure if the two callsites could
currently ever both occur on the same run of uv)

## Test Plan

I've tested this manually on linux (WSL ubuntu) and windows, though not
on aarch64-apple-darwin as I don't have a machine running that. I would
appreciate if someone would double-check that it works on such machines.

As discussed in the original PR, this change is pretty hard to test due
to the fact that the behavior only occurs if stderr is connected to a
tty. I experimented with using pseudoterminals to test this but it's
still quite tricky due to the lack of x-platform non-blocking reads on
the pty.

<!-- How was it tested? -->
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Mar 6, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [astral-sh/uv](https://github.com/astral-sh/uv) | patch | `0.6.3` -> `0.6.4` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>astral-sh/uv (astral-sh/uv)</summary>

### [`v0.6.4`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#064)

[Compare Source](astral-sh/uv@0.6.3...0.6.4)

##### Enhancements

-   Upgrade pypy3.10 to v7.3.19 ([#&#8203;11814](astral-sh/uv#11814))
-   Allow configuring log verbosity from the CLI (i.e., `-vvv`) ([#&#8203;11758](astral-sh/uv#11758))
-   Warn when duplicate index names found in single file ([#&#8203;11824](astral-sh/uv#11824))

##### Bug fixes

-   Always store registry index on resolution packages ([#&#8203;11815](astral-sh/uv#11815))
-   Avoid error on relative paths in `uv tool uninstall` ([#&#8203;11889](astral-sh/uv#11889))
-   Avoid silently dropping errors in directory enumeration ([#&#8203;11890](astral-sh/uv#11890))
-   Disable interactive git terminal prompts during fetches ([#&#8203;11744](astral-sh/uv#11744))
-   Discover Windows registry (PEP 514) Python versions across 32/64-bit ([#&#8203;11801](astral-sh/uv#11801))
-   Don't panic on Ctrl-C in confirm prompt ([#&#8203;11706](astral-sh/uv#11706))
-   Fix non-directory in workspace on Windows ([#&#8203;11833](astral-sh/uv#11833))
-   Make interpreter caching robust to OS upgrades ([#&#8203;11875](astral-sh/uv#11875))
-   Respect `include-system-site-packages` in layered environments ([#&#8203;11873](astral-sh/uv#11873))
-   Suggest `uv tool update-shell` in PowerShell ([#&#8203;11846](astral-sh/uv#11846))
-   Update code page to `65001` before setting environment variables in virtual environments ([#&#8203;11831](astral-sh/uv#11831))
-   Use hash instead of full wheel name in wheels bucket ([#&#8203;11738](astral-sh/uv#11738))
-   Fix version string truncation while generating cache_key ([#&#8203;11830](astral-sh/uv#11830))
-   Explicitly handle ctrl-c in confirmation prompt instead of using a signal handler ([#&#8203;11897](astral-sh/uv#11897))

##### Performance

-   Avoid cloning to string when creating cache path ([#&#8203;11772](astral-sh/uv#11772))
-   Avoid redundant clones in version containment check ([#&#8203;11767](astral-sh/uv#11767))
-   Avoid string allocation when enumerating tool names ([#&#8203;11910](astral-sh/uv#11910))
-   Avoid using owned `String` for package name constructors ([#&#8203;11768](astral-sh/uv#11768))
-   Avoid using owned `String` in deserializers ([#&#8203;11764](astral-sh/uv#11764))
-   Migrate to `zlib-rs` (again) ([#&#8203;11894](astral-sh/uv#11894))
-   Remove unnecessary clones when adding package names ([#&#8203;11771](astral-sh/uv#11771))
-   Skip unquote allocation for non-quoted strings ([#&#8203;11813](astral-sh/uv#11813))
-   Use `SmallString` for filenames and URLs ([#&#8203;11765](astral-sh/uv#11765))
-   Use a Boxed slice for version specifiers ([#&#8203;11766](astral-sh/uv#11766))
-   Use matches over contains for extra value parsing ([#&#8203;11770](astral-sh/uv#11770))

##### Documentation

-   Avoid fallback to PyPI in mixed CPU/CUDA example ([#&#8203;11115](astral-sh/uv#11115))
-   Docs: Clarify that setting cache-keys overrides defaults ([#&#8203;11895](astral-sh/uv#11895))
-   Document our MSRV policy ([#&#8203;11898](astral-sh/uv#11898))
-   Fix reference to macOS cache path ([#&#8203;11845](astral-sh/uv#11845))
-   Fix typo in `no_default_groups` documentation and changelog ([#&#8203;11928](astral-sh/uv#11928))
-   Update the "Locking and syncing" page ([#&#8203;11647](astral-sh/uv#11647))
-   Update alternative indexes documentation to use new interface ([#&#8203;10826](astral-sh/uv#10826))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Did you mean [...]? + ctr-c => thread 'main2' panicked

2 participants