summaryrefslogtreecommitdiff
path: root/ext/napi/lib.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-01-13 22:17:25 +0100
committerGitHub <noreply@github.com>2023-01-13 22:17:25 +0100
commit225114166aa7426d4b93fa13635559029c5ba65d (patch)
treead450bcd2a68b49adbeaf21ec10c4652ca2af056 /ext/napi/lib.rs
parentd4767a1a876f06b3b4b703b79b16af3571f2f583 (diff)
fix(napi): allow cleanup hook to remove itself (#17402)
This commit fixes "cleanup hooks" in NAPI integration in two ways: - don't hold to RefCell's borrow while iterating over hooks - allow a hook to remove itself when being called
Diffstat (limited to 'ext/napi/lib.rs')
-rw-r--r--ext/napi/lib.rs29
1 files changed, 25 insertions, 4 deletions
diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs
index 57f73a0ca..22b0e3a08 100644
--- a/ext/napi/lib.rs
+++ b/ext/napi/lib.rs
@@ -343,11 +343,32 @@ pub struct NapiState {
impl Drop for NapiState {
fn drop(&mut self) {
- let mut hooks = self.env_cleanup_hooks.borrow_mut();
+ let hooks = {
+ let h = self.env_cleanup_hooks.borrow_mut();
+ h.clone()
+ };
+
// Hooks are supposed to be run in LIFO order
- let hooks = hooks.drain(..).rev();
- for (fn_ptr, data) in hooks {
- (fn_ptr)(data);
+ let hooks_to_run = hooks.into_iter().rev();
+
+ for hook in hooks_to_run {
+ // This hook might have been removed by a previous hook, in such case skip it here.
+ if !self
+ .env_cleanup_hooks
+ .borrow()
+ .iter()
+ .any(|pair| pair.0 == hook.0 && pair.1 == hook.1)
+ {
+ continue;
+ }
+
+ (hook.0)(hook.1);
+ {
+ self
+ .env_cleanup_hooks
+ .borrow_mut()
+ .retain(|pair| !(pair.0 == hook.0 && pair.1 == hook.1));
+ }
}
}
}