1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! Clears dialogs the engine raises while it is being created.
//!
//! Everything else this crate does about modal dialogs happens *after* there is
//! an engine to configure. One case cannot: the warning that sequence files
//! were left unreleased when the engine was last destroyed is raised during
//! construction of the engine object itself, from inside the COM call that
//! creates it. By the time a caller could set an option, the dialog is already
//! up and the calling thread is inside a modal loop.
//!
//! No station option turns it off. Debug options govern the two leak reports
//! raised at *shutdown*; this one is unconditional, and measured on a station
//! with every debug option already clear it still appears. So the only way a
//! headless host survives it is to close the window.
//!
//! The sweeper therefore runs on its own thread for the duration of the
//! creating call, closes what it finds, and stops. It is deliberately narrow:
//! it lives only across one call known to raise these, so a dialog a host puts
//! up later is never touched.
//!
//! # What this does not cover
//!
//! Detection is limited to windows owned by *this* process, which is the same
//! rule the watchdog uses and is what keeps it from closing windows belonging
//! to an editor or a service that happens to be running. A dialog raised by a
//! separate process is therefore invisible to it.
//!
//! That limit has not been ruled out for the unreleased-files warning itself.
//! It has been observed on a station while this sweeper reported a clean start,
//! which is consistent with the warning being owned by another process, and no
//! measurement has yet established which process owns it. Until that is
//! settled, treat an empty [`Engine::startup_dialogs`](crate::Engine::startup_dialogs)
//! as "nothing owned by this process asked anything", not as "no dialog
//! appeared".
use Arc;
use ;
use ;
use JoinHandle;
use DialogInfo;
/// How often to look while the creating call is in flight.
const POLL_INTERVAL: Duration = from_millis;
/// Closes dialogs on another thread while the creating call blocks this one.
pub
/// Polls for a dialog and closes each one until told to stop.