Skip to content

Commit a7721af

Browse files
committed
fix(test): terminate test window phnode on test runner reload
Add a beforeunload handler in SpecRunnerUtils that calls terminateNode() on the test iframe's Node engine when the test runner page reloads. This prevents orphaned phnode.exe processes from holding directory locks on Windows, which caused EBUSY errors in consecutive integration test runs. Also simplifies Terminal-integ-test afterAll by removing the Windows-specific 5s delay that was a workaround for the same issue.
1 parent 51ac411 commit a7721af

2 files changed

Lines changed: 16 additions & 25 deletions

File tree

test/spec/SpecRunnerUtils.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,21 @@ define(function (require, exports, module) {
5454

5555
MainViewManager._initialize($("#mock-main-view"));
5656

57+
// When the test runner page reloads (e.g. switching test
58+
// categories), terminate the test window's Node engine so
59+
// its phnode.exe process and children (ESLint runners,
60+
// terminal shells) don't become orphans that hold directory
61+
// locks on Windows.
62+
window.addEventListener("beforeunload", function () {
63+
if (_testWindow && _testWindow.PhNodeEngine) {
64+
try {
65+
_testWindow.PhNodeEngine.terminateNode();
66+
} catch (e) {
67+
// ignore — test window may already be torn down
68+
}
69+
}
70+
});
71+
5772
function _getFileSystem() {
5873
return FileSystem;
5974
}

test/spec/Terminal-integ-test.js

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -55,39 +55,15 @@ define(function (require, exports, module) {
5555
afterAll(async function () {
5656
// Dispose all terminal PTY processes before teardown.
5757
// panel.hide() keeps terminals alive by design, so we
58-
// must explicitly kill them. On Windows, a shell whose
59-
// cwd is the temp directory locks it and prevents
60-
// cleanup by the next test run.
58+
// must explicitly kill them.
6159
if (testWindow) {
6260
try {
6361
const termModule = testWindow.brackets.getModule(
6462
"extensionsIntegrated/Terminal/main"
6563
);
6664
if (termModule && termModule._disposeAll) {
67-
// _disposeAll is async — awaits all kill
68-
// commands so PTYs are signalled before
69-
// the test window is torn down.
7065
await termModule._disposeAll();
7166
}
72-
// Wait for terminals to fully exit. On Windows,
73-
// taskkill is async and the shell process may
74-
// hold the cwd lock for several seconds after
75-
// the kill signal is sent.
76-
if (IS_WINDOWS) {
77-
await awaitsFor(function () {
78-
return testWindow.$(
79-
".terminal-flyout-item"
80-
).length === 0;
81-
}, "terminals to be disposed", 5000);
82-
// taskkill returns before the process fully
83-
// exits — the directory lock can persist for
84-
// a few more seconds. Wait for the OS to
85-
// release the lock so the next test run's
86-
// getTempTestDirectory can clean up.
87-
await new Promise(function (resolve) {
88-
setTimeout(resolve, 5000);
89-
});
90-
}
9167
} catch (e) {
9268
// test window may already be torn down
9369
}

0 commit comments

Comments
 (0)