@@ -16,15 +16,14 @@ const uuid = require('uuid')
1616const debug = require ( 'debug' )
1717const logger = debug ( 'electronpdf:' )
1818
19+ const WindowMaid = require ( './windowMaid' )
1920const wargs = require ( './args' )
2021
2122// CONSTANTS
2223/** Used to calculate browser dimensions based on PDF size */
2324const HTML_DPI = 96
2425/** Interval for which to check for hung windows, in milliseconds */
2526const HUNG_WINDOW_CLEANUP_INTERVAL = process . env . ELECTRONPDF_WINDOW_CLEANUP_INTERVAL || 1000 * 30 /* seconds */
26- /** How long a window can remain open before it is terminated, in milliseconds */
27- const HUNG_WINDOW_THRESHOLD = process . env . ELECTRONPDF_WINDOW_LIFE_THRESHOLD || 1000 * 60 * 5 /* minutes */
2827/** Used to determine browser size using a Micron -> Inch -> Pixel conversion */
2928const MICRONS_INCH_RATIO = 25400
3029/** When a ready event option is set, this is the default timeout. It is overridden by the wait option */
@@ -41,45 +40,8 @@ const DEFAULT_OPTIONS = {
4140 inMemory : false
4241}
4342
44- // Window Cache - Keep track of all windows created, and if any get stuck close
45- // them
46- const windowCache = { }
47- /**
48- * When a job creates a window it invoks this method so any memory leaks
49- * due to hung windows are prevented. This can happen if an uncaught exception
50- * occurs and job.destroy() is never invoked.
51- * @param job
52- */
53- function registerOpenWindow ( job ) {
54- const w = job . window
55- windowCache [ w . id ] = { job : job , window : w , lastUsed : Date . now ( ) }
56- }
57- /**
58- * Anytime a window is used this function should be invoked to update
59- * the lastUsed property in the window cache
60- * @param id
61- */
62- function touchWindow ( id ) {
63- windowCache [ id ] . lastUsed = Date . now ( )
64- }
65-
66- function cleanupHungWindows ( ) {
67- const now = Date . now ( )
68- const hungWindows = _ . filter ( windowCache ,
69- e => now - e . lastUsed > HUNG_WINDOW_THRESHOLD )
70- logger ( `checking hung windows. total windows: ${ _ . size ( windowCache ) } ` )
71- _ . forEach ( hungWindows , e => {
72- const windowContext = {
73- id : e . window . id ,
74- lifespan : now - e . lastUsed
75- }
76- e . job . emit ( 'window.termination' , windowContext )
77- delete windowCache [ e . window . id ]
78- e . job . destroy ( )
79- } )
80- }
81-
82- setInterval ( cleanupHungWindows , HUNG_WINDOW_CLEANUP_INTERVAL )
43+ // Use the maid to ensure we don't leak windows
44+ setInterval ( WindowMaid . cleanupHungWindows , HUNG_WINDOW_CLEANUP_INTERVAL )
8345
8446/**
8547 * A job should be created to process a given export opreation for one or more
@@ -143,7 +105,7 @@ class ExportJob extends EventEmitter {
143105 this . emit ( `${ RENDER_EVENT_PREFIX } start` )
144106 this . _launchBrowserWindow ( )
145107 const win = this . window
146- registerOpenWindow ( this )
108+ WindowMaid . registerOpenWindow ( this )
147109
148110 // TODO: Check for different domains, this is meant to support only a single origin
149111 const firstUrl = this . input [ 0 ]
@@ -227,6 +189,8 @@ class ExportJob extends EventEmitter {
227189 destroy ( ) {
228190 if ( this . window ) {
229191 try {
192+ logger ( `destroying job with window: ${ this . window . id } ` )
193+ WindowMaid . removeWindow ( this . window . id )
230194 this . window . close ( )
231195 } finally {
232196 this . window = undefined
@@ -291,7 +255,7 @@ class ExportJob extends EventEmitter {
291255 * @private
292256 */
293257 _initializeWindowForResource ( ) {
294- touchWindow ( this . window . id )
258+ WindowMaid . touchWindow ( this . window . id )
295259 // Reset the generated flag for each input URL because this same job/window
296260 // can be reused in this scenario
297261 this . generated = false
0 commit comments