Skip to content

Commit c9e6f55

Browse files
committed
fix: improve image extraction timeout handling
- Add proper cleanup function to release timeout resources - Wrap async image get in try-catch for error handling - Ensure timeout is cleared in all code paths - Apply fix to both extractImagesFromPage and extractPageContent This prevents potential resource leaks when image extraction times out or fails.
1 parent 19c7451 commit c9e6f55

File tree

1 file changed

+60
-12
lines changed

1 file changed

+60
-12
lines changed

src/pdf/extractor.ts

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,24 +248,48 @@ const extractImagesFromPage = async (
248248

249249
// Fallback to async callback-based get with timeout
250250
let resolved = false;
251-
const timeout = setTimeout(() => {
251+
let timeoutId: NodeJS.Timeout | null = null;
252+
253+
// Create a cleanup function to ensure resources are released
254+
const cleanup = () => {
255+
if (timeoutId !== null) {
256+
clearTimeout(timeoutId);
257+
timeoutId = null;
258+
}
259+
};
260+
261+
timeoutId = setTimeout(() => {
252262
if (!resolved) {
253263
resolved = true;
264+
cleanup();
254265
console.warn(
255266
`[PDF Reader MCP] Image extraction timeout for ${imageName} on page ${String(pageNum)}`
256267
);
257268
resolve(null);
258269
}
259270
}, 10000); // 10 second timeout as a safety net
260271

261-
page.objs.get(imageName, (imageData: unknown) => {
272+
try {
273+
page.objs.get(imageName, (imageData: unknown) => {
274+
if (!resolved) {
275+
resolved = true;
276+
cleanup();
277+
const result = processImageData(imageData);
278+
resolve(result);
279+
}
280+
});
281+
} catch (error: unknown) {
282+
// If get() throws synchronously, clean up and reject
262283
if (!resolved) {
263284
resolved = true;
264-
clearTimeout(timeout);
265-
const result = processImageData(imageData);
266-
resolve(result);
285+
cleanup();
286+
const message = error instanceof Error ? error.message : String(error);
287+
console.warn(
288+
`[PDF Reader MCP] Error in async image get for ${imageName}: ${message}`
289+
);
290+
resolve(null);
267291
}
268-
});
292+
}
269293
})
270294
);
271295

@@ -475,24 +499,48 @@ export const extractPageContent = async (
475499

476500
// Fallback to async callback-based get with timeout
477501
let resolved = false;
478-
const timeout = setTimeout(() => {
502+
let timeoutId: NodeJS.Timeout | null = null;
503+
504+
// Create a cleanup function to ensure resources are released
505+
const cleanup = () => {
506+
if (timeoutId !== null) {
507+
clearTimeout(timeoutId);
508+
timeoutId = null;
509+
}
510+
};
511+
512+
timeoutId = setTimeout(() => {
479513
if (!resolved) {
480514
resolved = true;
515+
cleanup();
481516
console.warn(
482517
`[PDF Reader MCP] Image extraction timeout for ${imageName} on page ${String(pageNum)}`
483518
);
484519
resolve(null);
485520
}
486521
}, 10000); // 10 second timeout as a safety net
487522

488-
page.objs.get(imageName, (imageData: unknown) => {
523+
try {
524+
page.objs.get(imageName, (imageData: unknown) => {
525+
if (!resolved) {
526+
resolved = true;
527+
cleanup();
528+
const result = processImageData(imageData);
529+
resolve(result);
530+
}
531+
});
532+
} catch (error: unknown) {
533+
// If get() throws synchronously, clean up and reject
489534
if (!resolved) {
490535
resolved = true;
491-
clearTimeout(timeout);
492-
const result = processImageData(imageData);
493-
resolve(result);
536+
cleanup();
537+
const message = error instanceof Error ? error.message : String(error);
538+
console.warn(
539+
`[PDF Reader MCP] Error in async image get for ${imageName}: ${message}`
540+
);
541+
resolve(null);
494542
}
495-
});
543+
}
496544
})
497545
);
498546

0 commit comments

Comments
 (0)