1use std::sync::atomic::Ordering;
3
4use crate::{SignalHandlerMode, NEXT_MAP_INDEX, REGISTER, SIGNAL_HANDLER_MODE};
5
6pub fn cleanup_tempfiles() {
15 let current_pid = std::process::id();
16 let one_past_last_index = NEXT_MAP_INDEX.load(Ordering::SeqCst);
17 for idx in 0..one_past_last_index {
18 if let Some(entry) = REGISTER.try_entry(idx) {
19 entry.and_modify(|tempfile| {
20 if tempfile
21 .as_ref()
22 .map_or(false, |tf| tf.owning_process_id == current_pid)
23 {
24 if let Some(tempfile) = tempfile.take() {
25 tempfile.drop_without_deallocation();
26 }
27 }
28 });
29 }
30 }
31}
32
33#[cfg(not(windows))]
35pub(crate) fn cleanup_tempfiles_nix(sig: &libc::siginfo_t) {
36 cleanup_tempfiles();
37 let restore_original_behaviour = SignalHandlerMode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour as usize;
38 if SIGNAL_HANDLER_MODE.load(std::sync::atomic::Ordering::SeqCst) == restore_original_behaviour {
39 signal_hook::low_level::emulate_default_handler(sig.si_signo).ok();
40 }
41}
42
43#[cfg(windows)]
45pub(crate) fn cleanup_tempfiles_windows() {
46 cleanup_tempfiles();
47 let restore_original_behaviour = SignalHandlerMode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour as usize;
48 if SIGNAL_HANDLER_MODE.load(std::sync::atomic::Ordering::SeqCst) == restore_original_behaviour {
49 signal_hook::low_level::emulate_default_handler(signal_hook::consts::SIGTERM).ok();
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use std::path::Path;
56
57 use crate::{AutoRemove, ContainingDirectory};
58
59 fn filecount_in(path: impl AsRef<Path>) -> usize {
60 std::fs::read_dir(path).expect("valid dir").count()
61 }
62
63 #[test]
64 fn various_termination_signals_remove_tempfiles_unconditionally() -> Result<(), Box<dyn std::error::Error>> {
65 crate::setup(Default::default());
66 let dir = tempfile::tempdir()?;
67 for sig in signal_hook::consts::TERM_SIGNALS {
68 let _tempfile = crate::new(dir.path(), ContainingDirectory::Exists, AutoRemove::Tempfile)?;
69 assert_eq!(
70 filecount_in(dir.path()),
71 1,
72 "only one tempfile exists no matter the iteration"
73 );
74 signal_hook::low_level::raise(*sig)?;
75 assert_eq!(
76 filecount_in(dir.path()),
77 0,
78 "the signal triggers removal but won't terminate the process (anymore)"
79 );
80 }
81 Ok(())
82 }
83}