cyfs_util/process/
process_mutex.rs

1use named_lock::{NamedLock, NamedLockGuard};
2
3extern crate lazy_static;
4use lazy_static::lazy_static;
5use std::sync::Mutex;
6
7pub struct ProcessMutex {
8    // Compatibility with older versions is in /tmp/
9    prev_lock: NamedLock,
10
11    named_lock: NamedLock,
12}
13
14impl ProcessMutex {
15    pub fn new(service_name: &str) -> ProcessMutex {
16        let name = format!("cyfs_plock_{}", service_name);
17        let named_lock;
18        #[cfg(unix)]
19        {
20            let locks_folder = crate::get_cyfs_root_path().join("run/locks");
21            if !locks_folder.is_dir() {
22                if let Err(e) = std::fs::create_dir_all(&locks_folder) {
23                    error!(
24                        "create run/locks folder error! folder={}, err={}",
25                        locks_folder.display(),
26                        e
27                    );
28                }
29            }
30
31            let lock_file = locks_folder.join(&format!("{}.lock", name));
32            named_lock = NamedLock::with_path(lock_file).unwrap();
33        }
34        #[cfg(not(unix))]
35        {
36            named_lock = NamedLock::create(&name).unwrap();
37        }
38
39        Self {
40            prev_lock: NamedLock::create(&name).unwrap(),
41            named_lock,
42        }
43    }
44
45    pub fn acquire(&self) -> Option<NamedLockGuard> {
46        match self.prev_lock.try_lock() {
47            Ok(_guard) => {
48                // do nothing
49            }
50            Err(_) => {
51                // old proc old must be holded by other process!
52                return None;
53            }
54        }
55
56        match self.named_lock.try_lock() {
57            Ok(guard) => {
58                Some(guard)
59            }
60
61            Err(_e) => {
62                None
63            }
64        }
65    }
66}
67
68pub(crate) struct ServiceName(String);
69
70impl ServiceName {
71    pub fn new() -> ServiceName {
72        ServiceName("".to_owned())
73    }
74
75    pub fn init(&mut self, service_name: &str) {
76
77        // 可能被多次初始化,但每次初始化name后都会马上使用
78        assert!(self.0.is_empty());
79        self.0 = service_name.to_owned();
80    }
81
82    pub fn detach(&mut self) -> String {
83        self.0.split_off(0)
84    }
85}
86
87// 保持对guard的引用,避免释放
88static mut LOCK_GUARD_HOLDER: Option<NamedLockGuard<'static>> = None;
89
90lazy_static! {
91    pub(crate) static ref SERVICE_NAME: Mutex<ServiceName> = {
92        return Mutex::new(ServiceName::new());
93    };
94
95    pub(crate) static ref CURRENT_PROCESS_MUTEX: ProcessMutex = {
96        let name = SERVICE_NAME.lock().unwrap().detach();
97        assert!(!name.is_empty());
98
99        ProcessMutex::new(&name)
100    };
101
102    pub(crate) static ref CURRENT_PROC_LOCK: bool = {
103        let guard = CURRENT_PROCESS_MUTEX.acquire();
104        if guard.is_none() {
105            false
106        } else {
107            unsafe {
108                LOCK_GUARD_HOLDER = guard;
109            }
110            
111            true
112        }
113    };
114}