diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-07-12 01:27:46 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-07-16 01:02:47 +0900 |
| commit | ba23ea4f22b5482d036706124a196fa03ef4b521 (patch) | |
| tree | f743427e11f8ad7e08a041900f1e6aa5b67a7cd0 /crates/shirabe/src/command/diagnose_command.rs | |
| parent | e588920985c71eaa652a292db2dd1d75b73712e4 (diff) | |
| download | php-shirabe-ba23ea4f22b5482d036706124a196fa03ef4b521.tar.gz php-shirabe-ba23ea4f22b5482d036706124a196fa03ef4b521.tar.zst php-shirabe-ba23ea4f22b5482d036706124a196fa03ef4b521.zip | |
fix(proxy-manager): correct singleton lifecycle and simplify to a plain Mutex
reset() eagerly rebuilt the ProxyManager singleton immediately,
capturing env vars before a caller could set them for the next
request. PHP's reset() just nulls the static instance; getInstance()
lazily constructs on next use. Match that so proxy env vars set after
reset() are observed.
get_instance() also ensured the singleton was constructed under its
own lock, dropped that lock, and returned the bare Mutex; every caller
then took a second, independent lock. A reset() landing in that gap
would leave the caller observing None and panicking on
.as_ref().unwrap(), a state the old eager-reconstructing reset() could
not produce. Return the already-locked MutexGuard from get_instance()
instead, so construction and use happen under one lock, and update all
call sites accordingly.
Holding that guard across a loop body then deadlocked in
diagnose_command, since check_http_proxy transitively re-enters
get_instance() via HttpDownloader -> CurlDownloader, and
std::sync::Mutex is not reentrant. Re-acquire the lock fresh each
iteration with a short-lived guard instead.
Finally, Mutex::new is a const fn, so the OnceLock wrapper around it
was unnecessary indirection; a bare static Mutex<Option<ProxyManager>>
initializes to the same state without the get_or_init/get dance.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/command/diagnose_command.rs')
| -rw-r--r-- | crates/shirabe/src/command/diagnose_command.rs | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs index e7fb9c74..e457fbb2 100644 --- a/crates/shirabe/src/command/diagnose_command.rs +++ b/crates/shirabe/src/command/diagnose_command.rs @@ -338,7 +338,6 @@ impl Command for DiagnoseCommand { } } - let proxy_manager = ProxyManager::get_instance(); let protos: Vec<&str> = if config.borrow_mut().get("disable-tls").as_bool() == Some(true) { vec!["http"] } else { @@ -346,9 +345,11 @@ impl Command for DiagnoseCommand { }; let proxy_check_result: anyhow::Result<(), anyhow::Error> = (|| -> anyhow::Result<()> { for proto in &protos { - let proxy = proxy_manager - .lock() - .unwrap() + // Compute the proxy under a short-lived lock: `check_http_proxy` below transitively + // re-enters `ProxyManager::get_instance()` (via HttpDownloader -> CurlDownloader / + // RemoteFilesystem), and `std::sync::Mutex` is not reentrant, so the guard must not + // still be held when that call happens. + let proxy = ProxyManager::get_instance() .as_ref() .unwrap() .get_proxy_for_request(&format!("{}://repo.packagist.org", proto)) |
