@@ -2,17 +2,15 @@ use std::{
22 error:: Error ,
33 fmt,
44 fs:: {
5- self ,
65 File ,
76 OpenOptions ,
87 } ,
9- io:: Write ,
108 ops,
9+ os:: unix:: fs:: OpenOptionsExt ,
1110 path:: {
1211 Path ,
1312 PathBuf ,
1413 } ,
15- process,
1614} ;
1715
1816#[ cfg( unix) ] use nix:: fcntl:: {
@@ -30,17 +28,17 @@ pub struct LockFile {
3028
3129#[ derive( Debug ) ]
3230pub struct LockFileError {
33- pub path : PathBuf ,
34- pid : u32 ,
31+ pub path : PathBuf ,
32+ pub message : Option < String > ,
3533}
3634
3735impl fmt:: Display for LockFileError {
3836 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
39- if self . pid == 0 {
40- write ! ( f, "failed to acquire lock at {}" , self . path. display( ) )
41- } else {
42- write ! ( f, "another watt daemon is running (PID: {})" , self . pid)
37+ write ! ( f, "failed to acquire lock on {}" , self . path. display( ) ) ?;
38+ if let Some ( msg) = & self . message {
39+ write ! ( f, ": {}" , msg) ?;
4340 }
41+ Ok ( ( ) )
4442 }
4543}
4644
@@ -65,17 +63,13 @@ impl LockFile {
6563 & self . path
6664 }
6765
68- pub fn acquire (
69- lock_path : & Path ,
70- force : bool ,
71- ) -> Result < Option < Self > , LockFileError > {
72- let pid = process:: id ( ) ;
73-
66+ pub fn acquire ( lock_path : & Path ) -> Result < Self , LockFileError > {
7467 #[ allow( clippy:: suspicious_open_options) ]
7568 let file = OpenOptions :: new ( )
7669 . create ( true )
7770 . read ( true )
7871 . write ( true )
72+ . mode ( 0o600 )
7973 . open ( lock_path)
8074 . map_err ( |error| {
8175 log:: error!(
@@ -84,96 +78,34 @@ impl LockFile {
8478 error
8579 ) ;
8680 LockFileError {
87- path : lock_path. to_owned ( ) ,
88- pid : 0 ,
81+ path : lock_path. to_owned ( ) ,
82+ message : Some ( error . to_string ( ) ) ,
8983 }
9084 } ) ?;
9185
92- let mut lock = match Flock :: lock ( file, FlockArg :: LockExclusiveNonblock ) {
93- Ok ( lock) => lock,
94- Err ( ( _, nix:: errno:: Errno :: EWOULDBLOCK ) ) => {
95- let Some ( existing_pid) = Self :: read_pid ( lock_path) else {
96- if force {
97- log:: warn!(
98- "could not determine PID of existing watt instance, starting \
99- anyway",
100- ) ;
101- return Ok ( None ) ;
102- }
103-
104- return Err ( LockFileError {
105- path : lock_path. to_owned ( ) ,
106- pid : 0 ,
107- } ) ;
108- } ;
109-
110- if force {
111- log:: warn!(
112- "another watt instance is running (PID: {existing_pid}), starting \
113- anyway",
86+ let lock = Flock :: lock ( file, FlockArg :: LockExclusiveNonblock ) . map_err (
87+ |( _, error) | {
88+ let message = if error == nix:: errno:: Errno :: EWOULDBLOCK {
89+ log:: error!(
90+ "another watt instance is already running (lock held on {})" ,
91+ lock_path. display( )
11492 ) ;
115- return Ok ( None ) ;
116- }
117-
118- return Err ( LockFileError {
119- path : lock_path. to_owned ( ) ,
120- pid : existing_pid,
121- } ) ;
122- } ,
93+ Some ( "another instance is running" . to_string ( ) )
94+ } else {
95+ log:: error!( "failed to acquire lock: {}" , error) ;
96+ Some ( error. to_string ( ) )
97+ } ;
12398
124- Err ( ( _, error) ) => {
125- log:: error!( "failed to acquire lock: {}" , error) ;
126- return Err ( LockFileError {
99+ LockFileError {
127100 path : lock_path. to_owned ( ) ,
128- pid : 0 ,
129- } ) ;
101+ message ,
102+ }
130103 } ,
131- } ;
132-
133- if let Err ( e) = lock. set_len ( 0 ) {
134- log:: error!( "failed to truncate lock file: {}" , e) ;
135- return Err ( LockFileError {
136- path : lock_path. to_owned ( ) ,
137- pid : 0 ,
138- } ) ;
139- }
140-
141- if let Err ( e) = lock. write_all ( format ! ( "{pid}\n " ) . as_bytes ( ) ) {
142- log:: error!( "failed to write PID to lock file: {}" , e) ;
143- return Err ( LockFileError {
144- path : lock_path. to_owned ( ) ,
145- pid : 0 ,
146- } ) ;
147- }
104+ ) ?;
148105
149- if let Err ( e) = lock. sync_all ( ) {
150- log:: error!( "failed to sync lock file: {}" , e) ;
151- return Err ( LockFileError {
152- path : lock_path. to_owned ( ) ,
153- pid : 0 ,
154- } ) ;
155- }
156-
157- Ok ( Some ( LockFile {
106+ Ok ( LockFile {
158107 lock,
159108 path : lock_path. to_owned ( ) ,
160- } ) )
161- }
162-
163- fn read_pid ( lock_path : & Path ) -> Option < u32 > {
164- match fs:: read_to_string ( lock_path) {
165- Ok ( content) => content. trim ( ) . parse ( ) . ok ( ) ,
166- Err ( _) => None ,
167- }
168- }
169-
170- pub fn release ( & mut self ) {
171- let _ = fs:: remove_file ( & self . path ) ;
172- }
173- }
174-
175- impl Drop for LockFile {
176- fn drop ( & mut self ) {
177- self . release ( ) ;
109+ } )
178110 }
179111}
0 commit comments