gix_tempfile/
registry.rs

1use crate::REGISTRY;
2
3/// Remove all tempfiles still registered on our global registry, and leak their data to be signal-safe.
4/// This happens on a best-effort basis with all errors being ignored.
5///
6/// # Safety
7/// Note that Mutexes of any kind are not allowed, and so aren't allocation or deallocation of memory.
8/// We are using lock-free datastructures and sprinkle in `std::mem::forget` to avoid deallocating.
9/// Most importantly, we use `try_lock()` which uses an atomic int only without blocking, making our register method safe to use,
10/// at the expense of possibly missing a lock file if another thread wants to obtain it or put it back
11/// (i.e. mutates the registry shard).
12pub fn cleanup_tempfiles_signal_safe() {
13    let current_pid = std::process::id();
14    #[cfg(feature = "hp-hashmap")]
15    {
16        use std::sync::atomic::Ordering;
17
18        use crate::NEXT_MAP_INDEX;
19
20        let one_past_last_index = NEXT_MAP_INDEX.load(Ordering::SeqCst);
21        for idx in 0..one_past_last_index {
22            if let Some(entry) = REGISTRY.try_entry(idx) {
23                entry.and_modify(|tempfile| {
24                    if tempfile.as_ref().is_some_and(|tf| tf.owning_process_id == current_pid) {
25                        if let Some(tempfile) = tempfile.take() {
26                            tempfile.drop_without_deallocation();
27                        }
28                    }
29                });
30            }
31        }
32    }
33    #[cfg(not(feature = "hp-hashmap"))]
34    {
35        REGISTRY.for_each(|tf| {
36            if tf.as_ref().map_or(false, |tf| tf.owning_process_id == current_pid) {
37                if let Some(tf) = tf.take() {
38                    tf.drop_without_deallocation();
39                }
40            }
41        });
42    }
43}
44
45/// Remove all tempfiles still registered on our global registry.
46/// This happens on a best-effort basis with all errors being ignored.
47///
48/// # Note
49///
50/// Must not be called from within signal hooks. For that, use [`cleanup_tempfiles_signal_safe()`].
51pub fn cleanup_tempfiles() {
52    let current_pid = std::process::id();
53    #[cfg(feature = "hp-hashmap")]
54    REGISTRY.iter_mut().for_each(|mut tf| {
55        if tf.as_ref().is_some_and(|tf| tf.owning_process_id == current_pid) {
56            tf.take();
57        }
58    });
59    #[cfg(not(feature = "hp-hashmap"))]
60    REGISTRY.for_each(|tf| {
61        if tf.as_ref().map_or(false, |tf| tf.owning_process_id == current_pid) {
62            tf.take();
63        }
64    });
65}