rlgwebd.js: prevent races when reading ttyrecs.
DglSession objects read a 12-byte TTYREC header, extract therefrom the length of the data chunk, and then read the data. In between these two reads, the file watcher could trigger another readchunk() invocation, which might attempt to read a header from the beginning of the data chunk. This usually results in expecting a data chunk of several GB and failing to create a Buffer for it. The race is remedied by setting a flag on the DglSession object whenever readchunk() is called, clearing it when both reads complete, and refusing to read if it is already set.
This commit is contained in:
parent
547387846f
commit
3c88c233b4
1 changed files with 14 additions and 2 deletions
16
rlgwebd.js
16
rlgwebd.js
|
|
@ -205,6 +205,9 @@ function DglSession(filename) {
|
|||
this.pname = basename.slice(0, firstsep);
|
||||
var fname = basename.slice(firstsep + 1);
|
||||
this.ttyrec = path.join("/dgldir/ttyrec", this.pname, this.gname, fname);
|
||||
/* Flag to prevent multiple handlers from reading simultaneously and
|
||||
* getting into a race. */
|
||||
this.reading = false;
|
||||
this.framebuf = new Buffer(1024);
|
||||
this.frameoff = 0;
|
||||
this.framepush = function(chunk) {
|
||||
|
|
@ -229,17 +232,24 @@ function DglSession(filename) {
|
|||
this.frameoff += chunk.length;
|
||||
};
|
||||
this.readchunk = function () {
|
||||
if (this.reading)
|
||||
return;
|
||||
this.reading = true;
|
||||
var header = new Buffer(12);
|
||||
fs.read(ss.fd, header, 0, 12, null, function (err, n, buf) {
|
||||
/* Stop recursion if end of file has been reached. */
|
||||
if (err || n < 12)
|
||||
if (err || n < 12) {
|
||||
ss.reading = false;
|
||||
return;
|
||||
}
|
||||
var datalen = buf.readUInt32LE(8);
|
||||
//tslog("Allocating %d bytes", datalen);
|
||||
var databuf = new Buffer(datalen);
|
||||
fs.read(ss.fd, databuf, 0, datalen, null, function (err, n, buf) {
|
||||
if (err || n < datalen)
|
||||
ss.reading = false;
|
||||
if (err || n < datalen) {
|
||||
return;
|
||||
}
|
||||
/* Process the data */
|
||||
ss.framepush(buf);
|
||||
ss.emit("data", buf);
|
||||
|
|
@ -278,6 +288,8 @@ function DglSession(filename) {
|
|||
};
|
||||
this.close = function () {
|
||||
this.watcher.close()
|
||||
/* Ensure all data is handled before quitting. */
|
||||
this.readchunk();
|
||||
fs.close(this.fd);
|
||||
this.emit("close");
|
||||
tslog("DGL %s: closed", ss.tag());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue