Skip to content

Commit 7fb7030

Browse files
mcollinaaduh95
authored andcommitted
repl: fix flaky test-repl-programmatic-history
The test was flaky because the FileHandle for the history file could be garbage collected before being explicitly closed, causing ERR_INVALID_STATE errors when the handle was already closed by the GC finalizer. This fix adds an explicit closeHandle() method to ReplHistory and ensures that REPLServer.close() waits for the history file handle to be properly closed before completing the close operation. Refs: nodejs/reliability#1450 PR-URL: #61614 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent 9409d30 commit 7fb7030

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

lib/internal/repl/history.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const kResolveHistoryPath = Symbol('_kResolveHistoryPath');
5858
const kReplHistoryMessage = Symbol('_kReplHistoryMessage');
5959
const kFlushHistory = Symbol('_kFlushHistory');
6060
const kGetHistoryPath = Symbol('_kGetHistoryPath');
61+
const kCloseHandle = Symbol('_kCloseHandle');
6162

6263
class ReplHistory {
6364
constructor(context, options) {
@@ -393,15 +394,29 @@ class ReplHistory {
393394
}
394395
this[kContext].off('line', this[kOnLine].bind(this));
395396

397+
await this[kCloseHandle]();
398+
}
399+
400+
async [kCloseHandle]() {
396401
if (this[kHistoryHandle] !== null) {
402+
const handle = this[kHistoryHandle];
403+
this[kHistoryHandle] = null;
397404
try {
398-
await this[kHistoryHandle].close();
405+
await handle.close();
399406
} catch (err) {
400407
debug('Error closing history file:', err);
401408
}
402409
}
403410
}
404411

412+
/**
413+
* Closes the history file handle.
414+
* @returns {Promise<void>}
415+
*/
416+
closeHandle() {
417+
return this[kCloseHandle]();
418+
}
419+
405420
[kReplHistoryMessage]() {
406421
if (this[kHistory].length === 0) {
407422
ReplHistory[kWriteToOutput](

lib/repl.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,12 +1039,18 @@ class REPLServer extends Interface {
10391039
this[kBufferedCommandSymbol] = '';
10401040
}
10411041
close() {
1042-
if (this.terminal && this.historyManager.isFlushing && !this._closingOnFlush) {
1042+
if (this.terminal && this.historyManager?.isFlushing && !this._closingOnFlush) {
10431043
this._closingOnFlush = true;
1044-
this.once('flushHistory', () => super.close());
1044+
this.once('flushHistory', () => this.close());
10451045

10461046
return;
10471047
}
1048+
// Ensure the history file handle is closed before completing
1049+
if (this.terminal && this.historyManager?.closeHandle && !this._historyHandleClosed) {
1050+
this._historyHandleClosed = true;
1051+
this.historyManager.closeHandle().then(() => super.close());
1052+
return;
1053+
}
10481054
process.nextTick(() => super.close());
10491055
}
10501056
createContext() {

0 commit comments

Comments
 (0)