Skip to content

Commit e4aa61e

Browse files
authored
Merge pull request #2 from sefinek/codex/fix-err_use_after_close-in-updatedb-script
Prevent readline from resuming after it is closed
2 parents 847a23a + 966b368 commit e4aa61e

File tree

1 file changed

+96
-20
lines changed

1 file changed

+96
-20
lines changed

tools/updatedb.js

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,9 @@ async function processCountryData(src, dest) {
346346
let tstart = Date.now();
347347
const datFile = fs.createWriteStream(dataFile);
348348

349-
function processLine(line) {
350-
const fields = CSVtoArray(line);
351-
if (!fields || fields.length < 6) return log.warn('Malformed line detected:', line);
349+
function processLine(line) {
350+
const fields = CSVtoArray(line);
351+
if (!fields || fields.length < 6) return log.warn('Malformed line detected:', line);
352352

353353
lines++;
354354

@@ -405,15 +405,53 @@ async function processCountryData(src, dest) {
405405
}
406406
}
407407

408-
const rl = readline.createInterface({ input: fs.createReadStream(tmpDataFile), crlfDelay: Infinity });
409-
let i = 0;
410-
for await (const line of rl) {
411-
i++;
412-
if (i === 1) continue;
413-
await processLine(line);
414-
}
415-
datFile.close();
416-
log.done();
408+
await new Promise((resolve, reject) => {
409+
const rl = readline.createInterface({ input: fs.createReadStream(tmpDataFile), crlfDelay: Infinity });
410+
let settled = false;
411+
let i = 0;
412+
413+
function finish(err) {
414+
if (settled) return;
415+
settled = true;
416+
if (!rl.closed) rl.close();
417+
if (err) reject(err);
418+
else resolve();
419+
}
420+
421+
function resume() {
422+
if (!settled && !rl.closed) rl.resume();
423+
}
424+
425+
rl.on('line', line => {
426+
rl.pause();
427+
i++;
428+
if (i === 1) {
429+
resume();
430+
return;
431+
}
432+
433+
let result;
434+
try {
435+
result = processLine(line);
436+
} catch (err) {
437+
finish(err);
438+
return;
439+
}
440+
441+
if (result && typeof result.then === 'function') {
442+
result.then(() => {
443+
resume();
444+
}).catch(finish);
445+
} else {
446+
resume();
447+
}
448+
});
449+
450+
rl.on('close', () => finish());
451+
rl.on('error', finish);
452+
});
453+
datFile.close();
454+
log.done();
417455
}
418456

419457
async function processCityData(src, dest) {
@@ -514,14 +552,52 @@ async function processCityData(src, dest) {
514552
}
515553
}
516554

517-
const rl = readline.createInterface({ input: fs.createReadStream(tmpDataFile), crlfDelay: Infinity });
518-
let i = 0;
519-
for await (const line of rl) {
520-
i++;
521-
if (i === 1) continue;
522-
await processLine(line);
523-
}
524-
datFile.close();
555+
await new Promise((resolve, reject) => {
556+
const rl = readline.createInterface({ input: fs.createReadStream(tmpDataFile), crlfDelay: Infinity });
557+
let settled = false;
558+
let i = 0;
559+
560+
function finish(err) {
561+
if (settled) return;
562+
settled = true;
563+
if (!rl.closed) rl.close();
564+
if (err) reject(err);
565+
else resolve();
566+
}
567+
568+
function resume() {
569+
if (!settled && !rl.closed) rl.resume();
570+
}
571+
572+
rl.on('line', line => {
573+
rl.pause();
574+
i++;
575+
if (i === 1) {
576+
resume();
577+
return;
578+
}
579+
580+
let result;
581+
try {
582+
result = processLine(line);
583+
} catch (err) {
584+
finish(err);
585+
return;
586+
}
587+
588+
if (result && typeof result.then === 'function') {
589+
result.then(() => {
590+
resume();
591+
}).catch(finish);
592+
} else {
593+
resume();
594+
}
595+
});
596+
597+
rl.on('close', () => finish());
598+
rl.on('error', finish);
599+
});
600+
datFile.close();
525601
}
526602

527603
function processCityDataNames(src, dest, cb) {

0 commit comments

Comments
 (0)