Skip to content

Commit 71d7413

Browse files
authored
Merge pull request #12535 from quarto-dev/bugfix/7757
2 parents 5768c1f + 7f12078 commit 71d7413

File tree

5 files changed

+42
-10
lines changed

5 files changed

+42
-10
lines changed

news/changelog-1.7.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ All changes included in 1.7:
171171
- A new folder `quarto-session-temp` can be created in `.quarto` to store temporary files created by Quarto during a rendering. Reminder: `.quarto` is for internal use of Quarto and should not be versioned (thus added to `.gitignore`).
172172
- ([fb38eb5](https://github.com/quarto-dev/quarto-cli/commit/fb38eb56c11e09f44cef58fd3b697ff24bb5a3f3)) Use the `latest` parser for Acorn when analyzing JS code imported from OJS blocks.
173173
- ([#7260](https://github.com/quarto-dev/quarto-cli/issues/7260)): Add support for `active` class in tabsets so the `.active` tab shows up by default.
174+
- ([#7757](https://github.com/quarto-dev/quarto-cli/issues/7757)): Session temporary files are now cleaned up when the session ends abnormally (e.g. `Ctrl+C`) also on Windows.
174175
- ([#8613](https://github.com/quarto-dev/quarto-cli/issues/8613)): Fix `giscus` color on load to support dark mode (by @kv9898).
175176
- ([#9867](https://github.com/quarto-dev/quarto-cli/issues/9867)): Blank lines are now trimmed in Raw HTML Table blocks.
176177
- ([#10532](https://github.com/quarto-dev/quarto-cli/issues/10532)): Changed default of `--headless=old` to `--headless` as [Chrome 132 has removed old headless mode](https://developer.chrome.com/blog/removing-headless-old-from-chrome) and only support new mode. To use old mode, set `QUARTO_CHROMIUM` to a [new `chrome-headless-shell` binary](https://developer.chrome.com/blog/chrome-headless-shell) or to an older chrome version (between 128 and 132). Set `QUARTO_CHROMIUM_HEADLESS_MODE` to `old` to use old headless mode with that compatible version.

src/core/main.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ export async function mainRunner(runner: Runner) {
2727
await initializeLogger(logOptions(args));
2828

2929
// install termination signal handlers
30+
31+
// Even though windows doesn't technically have signals, Deno
32+
// does the "expected" thing here and calls abend
33+
// on interruption.
34+
Deno.addSignalListener("SIGINT", abend);
3035
if (!isWindows) {
31-
Deno.addSignalListener("SIGINT", abend);
3236
Deno.addSignalListener("SIGTERM", abend);
3337
}
3438

src/core/once.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* once.ts
3+
*
4+
* Copyright (C) 2025 Posit Software, PBC
5+
*/
6+
7+
export const once = (fn: () => void) => {
8+
let called = false;
9+
return () => {
10+
if (!called) {
11+
called = true;
12+
fn();
13+
}
14+
};
15+
};

src/project/project-context.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ import { makeTimedFunctionAsync } from "../core/performance/function-times.ts";
104104
import { createProjectCache } from "../core/cache/cache.ts";
105105
import { createTempContext } from "../core/temp.ts";
106106

107+
import { onCleanup } from "../core/cleanup.ts";
108+
import { once } from "../core/once.ts";
109+
107110
export async function projectContext(
108111
path: string,
109112
notebookContext: NotebookContext,
@@ -314,11 +317,11 @@ export async function projectContext(
314317
isSingleFile: false,
315318
diskCache: await createProjectCache(join(dir, ".quarto")),
316319
temp,
317-
cleanup: () => {
320+
cleanup: once(() => {
318321
cleanupFileInformationCache(result);
319322
result.diskCache.close();
320323
temp.cleanup();
321-
},
324+
}),
322325
};
323326

324327
// see if the project [kProjectType] wants to filter the project config
@@ -357,7 +360,7 @@ export async function projectContext(
357360
config: configFiles,
358361
configResources: projectConfigResources(dir, projectConfig, type),
359362
};
360-
363+
onCleanup(result.cleanup);
361364
return result;
362365
} else {
363366
debug(`projectContext: Found Quarto project in ${dir}`);
@@ -408,11 +411,11 @@ export async function projectContext(
408411
isSingleFile: false,
409412
diskCache: await createProjectCache(join(dir, ".quarto")),
410413
temp,
411-
cleanup: () => {
414+
cleanup: once(() => {
412415
cleanupFileInformationCache(result);
413416
result.diskCache.close();
414417
temp.cleanup();
415-
},
418+
}),
416419
};
417420
const { files, engines } = await projectInputFiles(
418421
result,
@@ -425,6 +428,7 @@ export async function projectContext(
425428
config: configFiles,
426429
configResources: projectConfigResources(dir, projectConfig),
427430
};
431+
onCleanup(result.cleanup);
428432
return result;
429433
}
430434
} else {
@@ -486,11 +490,11 @@ export async function projectContext(
486490
isSingleFile: false,
487491
diskCache: await createProjectCache(join(temp.baseDir, ".quarto")),
488492
temp,
489-
cleanup: () => {
493+
cleanup: once(() => {
490494
cleanupFileInformationCache(context);
491495
context.diskCache.close();
492496
temp.cleanup();
493-
},
497+
}),
494498
};
495499
if (Deno.statSync(path).isDirectory) {
496500
const { files, engines } = await projectInputFiles(context);
@@ -503,6 +507,7 @@ export async function projectContext(
503507
context.files.input = [input];
504508
}
505509
debug(`projectContext: Found Quarto project in ${originalDir}`);
510+
onCleanup(context.cleanup);
506511
return context;
507512
} else {
508513
return undefined;

src/project/types/single-file/single-file.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ import { RenderFlags } from "../../../command/render/types.ts";
2020
import { MappedString } from "../../../core/mapped-text.ts";
2121
import { fileExecutionEngineAndTarget } from "../../../execute/engine.ts";
2222
import {
23+
cleanupFileInformationCache,
2324
projectFileMetadata,
2425
projectResolveBrand,
2526
projectResolveFullMarkdownForFile,
2627
} from "../../project-shared.ts";
2728
import { ExecutionEngine } from "../../../execute/types.ts";
2829
import { createProjectCache } from "../../../core/cache/cache.ts";
2930
import { globalTempContext } from "../../../core/temp.ts";
31+
import { once } from "../../../core/once.ts";
3032

3133
export async function singleFileProjectContext(
3234
source: string,
@@ -77,10 +79,15 @@ export async function singleFileProjectContext(
7779
isSingleFile: true,
7880
diskCache: await createProjectCache(projectCacheBaseDir),
7981
temp,
80-
cleanup: () => {
82+
cleanup: once(() => {
83+
cleanupFileInformationCache(result);
8184
result.diskCache.close();
82-
},
85+
}),
8386
};
87+
// because the single-file project is cleaned up with
88+
// the global text context, we don't need to register it
89+
// in the same way that we need to register the multi-file
90+
// projects.
8491
temp.onCleanup(result.cleanup);
8592
return result;
8693
}

0 commit comments

Comments
 (0)