Fix locking soundness in PersistentPlugin (#12182)

# Description

There were two problems in `PersistentPlugin` which could cause a
deadlock:

1. There were two mutexes being used, and `get()` could potentially hold
both simultaneously if it had to spawn. This won't necessarily cause a
deadlock on its own, but it does mean that lock order is sensitive

2. `set_gc_config()` called `flush()` while still holding the lock,
meaning that the GC thread had to proceed before the lock was released.
However, waiting for the GC thread to proceed could mean waiting for the
GC thread to call `stop()`, which itself would try to lock the mutex.
So, it's not safe to wait for the GC thread while the lock is held. This
is fixed now.

I've also reverted #12177, as @IanManske reported that this was also
happening for him on Linux, and it seems to be this problem which should
not be platform-specific at all. I believe this solves it.

# User-Facing Changes
None

# Tests + Formatting
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting
This commit is contained in:
Devyn Cairns
2024-03-12 16:22:29 -07:00
committed by GitHub
parent cd71372ea9
commit e1cfc96ee8
2 changed files with 40 additions and 52 deletions

View File

@ -193,10 +193,6 @@ fn custom_values_can_still_be_collapsed_after_stop() {
}
#[test]
#[cfg_attr(
target_os = "macos",
ignore = "Plugin GC tests are disabled temporarily on macOS because they get stuck"
)]
fn plugin_gc_can_be_configured_to_stop_plugins_immediately() {
// I know the test is to stop "immediately", but if we actually check immediately it could
// lead to a race condition. So there's a 1ms sleep just to be fair.
@ -232,10 +228,6 @@ fn plugin_gc_can_be_configured_to_stop_plugins_immediately() {
}
#[test]
#[cfg_attr(
target_os = "macos",
ignore = "Plugin GC tests are disabled temporarily on macOS because they get stuck"
)]
fn plugin_gc_can_be_configured_to_stop_plugins_after_delay() {
let out = nu_with_plugins!(
cwd: ".",
@ -293,10 +285,6 @@ fn plugin_gc_can_be_configured_to_stop_plugins_after_delay() {
}
#[test]
#[cfg_attr(
target_os = "macos",
ignore = "Plugin GC tests are disabled temporarily on macOS because they get stuck"
)]
fn plugin_gc_can_be_configured_as_disabled() {
let out = nu_with_plugins!(
cwd: ".",
@ -329,10 +317,6 @@ fn plugin_gc_can_be_configured_as_disabled() {
}
#[test]
#[cfg_attr(
target_os = "macos",
ignore = "Plugin GC tests are disabled temporarily on macOS because they get stuck"
)]
fn plugin_gc_can_be_disabled_by_plugin() {
let out = nu_with_plugins!(
cwd: ".",
@ -350,10 +334,6 @@ fn plugin_gc_can_be_disabled_by_plugin() {
}
#[test]
#[cfg_attr(
target_os = "macos",
ignore = "Plugin GC tests are disabled temporarily on macOS because they get stuck"
)]
fn plugin_gc_does_not_stop_plugin_while_stream_output_is_active() {
let out = nu_with_plugins!(
cwd: ".",