-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
fs: make sure to write entire buffer #42434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4307397
b6b9680
a5bf600
523314a
d4c7a90
d0afc94
43f2529
4ff89b4
3869561
ab95708
43d9020
09b7994
be950ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -386,22 +386,71 @@ WriteStream.prototype.open = openWriteFs; | |
|
||
WriteStream.prototype._construct = _construct; | ||
|
||
function writeAll(data, size, pos, cb, retries = 0) { | ||
this[kFs].write(this.fd, data, 0, size, pos, (er, bytesWritten, buffer) => { | ||
if (er?.code === 'EAGAIN') { | ||
er = null; | ||
bytesWritten = 0; | ||
} | ||
|
||
if (this.destroyed || er) { | ||
return cb(er); | ||
} | ||
benjamingr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
ronag marked this conversation as resolved.
Show resolved
Hide resolved
|
||
this.bytesWritten += bytesWritten; | ||
|
||
retries = bytesWritten ? 0 : retries + 1; | ||
size -= bytesWritten; | ||
pos += bytesWritten; | ||
|
||
if (retries > 5) { | ||
cb(new Error('writev failed')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to be a proper error with code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestions? |
||
} else if (size) { | ||
writeAll(buffer.slice(bytesWritten), size, pos, cb, retries); | ||
} else { | ||
cb(); | ||
} | ||
}); | ||
} | ||
|
||
function writevAll(chunks, size, pos, cb, retries = 0) { | ||
this[kFs].writev(this.fd, chunks, this.pos, (er, bytesWritten, buffers) => { | ||
if (er?.code === 'EAGAIN') { | ||
er = null; | ||
bytesWritten = 0; | ||
} | ||
|
||
if (this.destroyed || er) { | ||
return cb(er); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will |
||
} | ||
|
||
this.bytesWritten += bytesWritten; | ||
|
||
retries = bytesWritten ? 0 : retries + 1; | ||
size -= bytesWritten; | ||
pos += bytesWritten; | ||
|
||
if (retries > 5) { | ||
cb(new Error('writev failed')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need a little help here... not sure what error to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lemme check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checked the existing codes, no idea either 😅 |
||
} else if (size) { | ||
writevAll([Buffer.concat(buffers).slice(bytesWritten)], size, pos, cb, retries); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're going to be concatenating, we may as well just do it once and call Ideally it would be great if we didn't have to even keep recreating arrays on retry. That might be a nice addition to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a cold path though? It should almost never happen. Is it worth optimizing for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It think it would be useful to get an idea of how often it happens (I personally have no idea). How cold is it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, if it does happen often then we have a lot of seriously broken software out there... I guess we would have quite a bit of reports.... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or people have learned to handle retries on their own? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don’t think you can actually detect that in this interface… there is nothing a user can do… it will just be corrupt w/o any way to detect or recover… so no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
makes sense, yeah sounds like a cold path to me. |
||
} else { | ||
cb(); | ||
} | ||
}); | ||
} | ||
|
||
WriteStream.prototype._write = function(data, encoding, cb) { | ||
this[kIsPerformingIO] = true; | ||
this[kFs].write(this.fd, data, 0, data.length, this.pos, (er, bytes) => { | ||
writeAll.call(this, data.length, data, this.pos, (er) => { | ||
this[kIsPerformingIO] = false; | ||
if (this.destroyed) { | ||
// Tell ._destroy() that it's safe to close the fd now. | ||
cb(er); | ||
return this.emit(kIoDone, er); | ||
} | ||
|
||
if (er) { | ||
return cb(er); | ||
} | ||
|
||
this.bytesWritten += bytes; | ||
cb(); | ||
cb(er); | ||
}); | ||
|
||
if (this.pos !== undefined) | ||
|
@@ -421,20 +470,15 @@ WriteStream.prototype._writev = function(data, cb) { | |
} | ||
|
||
this[kIsPerformingIO] = true; | ||
this[kFs].writev(this.fd, chunks, this.pos, (er, bytes) => { | ||
writevAll.call(this, size, chunks, this.pos, (er) => { | ||
this[kIsPerformingIO] = false; | ||
if (this.destroyed) { | ||
// Tell ._destroy() that it's safe to close the fd now. | ||
cb(er); | ||
return this.emit(kIoDone, er); | ||
} | ||
|
||
if (er) { | ||
return cb(er); | ||
} | ||
|
||
this.bytesWritten += bytes; | ||
cb(); | ||
cb(er); | ||
}); | ||
|
||
if (this.pos !== undefined) | ||
|
Uh oh!
There was an error while loading. Please reload this page.