@@ -75,6 +75,10 @@ pub struct ProxyInner {
7575 /// Capacity-one queue: each apply renders the latest state, so pending
7676 /// requests can be coalesced without losing a state change.
7777 wg_apply_tx : std:: sync:: mpsc:: SyncSender < ( ) > ,
78+ /// Held for the whole of an apply; `true` once the process is exiting.
79+ /// The apply writes the interface's private key through a temporary file,
80+ /// and exiting mid-write would leave that file behind.
81+ wg_apply_stopped : Mutex < bool > ,
7882 /// Only one registration mutates the routing table at a time anyway.
7983 /// Wait asynchronously rather than parking all RPC/blocking workers on it.
8084 registration_slot : Arc < Semaphore > ,
@@ -309,12 +313,28 @@ impl ProxyInner {
309313 /// Render the WireGuard config under the routing lock, then write and apply
310314 /// it after releasing that lock. Only the apply worker calls this.
311315 fn reconfigure_wg ( & self ) -> Result < ( ) > {
316+ let stopped = self
317+ . wg_apply_stopped
318+ . lock ( )
319+ . or_panic ( "Failed to lock wg apply" ) ;
320+ if * stopped {
321+ return Ok ( ( ) ) ;
322+ }
312323 let rendered = self . lock ( ) . generate_wg_config ( ) ;
313324 let result = rendered. and_then ( |rendered| apply_wg_config ( & self . config , & rendered) ) ;
314325 crate :: metrics:: record_wg_reconfigure ( result. is_ok ( ) ) ;
315326 result
316327 }
317328
329+ /// Wait for an apply in progress to finish and refuse any later one.
330+ /// Called on the way out of `main`, which does not join the worker thread.
331+ pub ( crate ) fn stop_wg_apply ( & self ) {
332+ * self
333+ . wg_apply_stopped
334+ . lock ( )
335+ . or_panic ( "Failed to lock wg apply" ) = true ;
336+ }
337+
318338 /// Queue a full apply on the worker. Every caller goes through here, so
319339 /// registrations, removals and reloads never wait on disk I/O or `wg`.
320340 pub ( crate ) fn request_wg_apply ( & self ) {
@@ -672,6 +692,7 @@ impl ProxyInner {
672692 state,
673693 notify_state_updated : Notify :: new ( ) ,
674694 wg_apply_tx,
695+ wg_apply_stopped : Mutex :: new ( false ) ,
675696 registration_slot : Arc :: new ( Semaphore :: new ( 1 ) ) ,
676697 my_app_id,
677698 auth_client,
0 commit comments