Closed
Labels
fsIssues and PRs related to file-system APIs and the fs module.Issues and PRs related to file-system APIs and the fs module.streamIssues and PRs related to Node.js streams.Issues and PRs related to Node.js streams.
Description
Platforms: Windows and Linux
Everything is fine as long as I use 10.7.0 or older. The problem starts when I go to 10.8.0 or newer.
I created a test project that reproduces the issue. It
- Provides two file, one UTF-8 and one random binary data
- First for the text file: creates a read stream and a write stream to copy the UTF-8 file
- Next creates a read stream and a write stream to copy the BINARY file
- Calculates SHA-256 during the read stream and during the write stream
- For visual inspection shows the beginning of each chunk read from the read stream (converted to text; the text and the binary data are easy to tell apart and the output of the binary is sanitized to not mess up the screen)
- The test code has Flow type annotations &mash; remove them if you don't want them (you can "npm install flow-bin flow-remove-types" for the latest flow version, and the 2nd package installs "flow-node" which is a frontend to node that strips the types when you run JS files through it instead of directly through node)
What you will see is that the write stream for the binary file gets the last chunk from the previous text file's read stream.
The read stream SHA-256 still is good, however, but the write stream's SHA-256 is not. The problem only seems to happen with binary files.
Test project output:
TEXT FILE TEST
TEXT CHUNK 5.3 Somatosensory Neurons have Receptive FieldsEach subcortical somatose... 65248
TEXT CHUNK ed the neuron’sreceptive field (Figure 5.3). The neuron’s receptive field ... 65242
TEXT CHUNK ed/represented. The receptive fields of neuronsinnervating/representing th... 4510
Original text file hash: 9101a84eb2320001628926e3c4decd09eff6680809e95a920db4e18afbcf0201
Read file calculated hash: 9101a84eb2320001628926e3c4decd09eff6680809e95a920db4e18afbcf0201
Write file calculated hash: 9101a84eb2320001628926e3c4decd09eff6680809e95a920db4e18afbcf0201
BINARY FILE TEST
BINARY CHUNK ed/represented. The receptive fields of neuronsinnervating/representing th.. 61008
BINARY CHUNK m5^gY5y"$ch86m&KmO}bD,P}r"sySZ6... 65536
BINARY CHUNK $J|0sd\hsrdh9Tn"?x<0ruZ3KD... 65536
BINARY CHUNK !>B2}REF7VEdK%Er(*$RuG"U$... 65536
...(a few more binary chunks)
BINARY CHUNK 1NI+`9sHRT)r.V%C&*"#*F_6HKw`... 47536
Original binary file hash: ee1758d957bac3706b6a0ad450ffaeab34d55d5c6d5988a8bef7ce72c8a7db85
Read file calculated hash: ee1758d957bac3706b6a0ad450ffaeab34d55d5c6d5988a8bef7ce72c8a7db85
Write file calculated hash: a9d6ee259f8d6315e5e59db7920d6389d6ebd60618d4a49a8550f8b3e340f06e
Metadata
Metadata
Assignees
Labels
fsIssues and PRs related to file-system APIs and the fs module.Issues and PRs related to file-system APIs and the fs module.streamIssues and PRs related to Node.js streams.Issues and PRs related to Node.js streams.
Activity
mscdex commentedon Aug 20, 2018
This issue tracker is for reporting bugs in node core and submitting feature requests for node core.
General help questions should be posted to the nodejs/help issue tracker instead.
Issues with third-party modules, npm, or other tools that use node, should be posted to the appropriate issue tracker for that project, unless it can be proven that the issue is in fact with node core and not the module/tool in question.
lll000111 commentedon Aug 20, 2018
jasnell commentedon Aug 20, 2018
Can I ask that you either copy the code into comments here or into a gist. I (and I know others here) are generally unwilling to download an opaque tar ball...
jasnell commentedon Aug 20, 2018
Also, I assume you mean Node.js 10.8.0 and not 10.0.8?
[-]Starting with 10.0.8 I get the last chunk of a previous read stream at the start of the next one[/-][+]Starting with 10.8.0 I get the last chunk of a previous read stream at the start of the next one[/+]lll000111 commentedon Aug 20, 2018
EDIT: type annotations removed
Test file 1: streams
Test file 2: main
jasnell commentedon Aug 20, 2018
This code is quite strange if all it is doing is copying files and calculating a hash while it happens. With the non-standard syntax here it is going to be impossible to determine if this really is a bug in Node.js, whatever transpiling utility you're using, or in your code. Can I ask you to remove the non-standard syntax from this and see if it has the same problem.
lll000111 commentedon Aug 20, 2018
It is standard javascript, it merely has type annotations. They don't do anything. "Transpiling" merely means removing the types. This is Flow, not TypeScript. I'll remove the types. They are just like comments.
lll000111 commentedon Aug 20, 2018
I updated the code above to remove the types.
The code is the way it is because the actual use case is a) cross platform (React Native, Browser, node.js) to read files on one node, send them via websocket, write them on another. That is why I have a frontend for streams, there is a different one on each platform. Just for the explanation, I think the code is simple enough, just standard stream things, I don't do anything fancy at all. I mean, The node.js part is just read a stream in chunks and write them to a write stream, Most of main.js is just to create a nice example.
And by the way, all that encoding stuff is necessary for the React Native platform which can do binary only using base64 encoding(!). Otherwise I would have only Buffers and no string streams.
jasnell commentedon Aug 20, 2018
FWIW, there is a much simpler way of doing what you're trying to do here, but I'm not going to go into that now.
@addaleax ... I'm wondering if the use of Promises here is causing some strange interaction with the changes from #21968, which landed in 10.8.0.
addaleax commentedon Aug 20, 2018
Looking into it, I think it’s indeed that PR, in that the more efficient usage of the underlying ArrayBuffers is what’s causing this:
This piece of your code doesn’t seem to do what it should; what if
data.byteOffsetis not zero? You’d still return data from the start of the underlying ArrayBuffer. Sorry to disappoint, but this really doesn’t look like a bug in Node…jasnell commentedon Aug 20, 2018
Ah, right, yep, just spotted that also. Prior to the change in #21968, that offset wouldn't really have mattered for
fsstreams but correct code still needs to account for it with arbitrary streams because that offset can definitely throw things off.jasnell commentedon Aug 20, 2018
@addaleax ... I'm wondering if we shouldn't at least add a comment to the stream docs advising folks that they need to pay attention to the
byteOffseton any buffer they receive.jasnell commentedon Aug 20, 2018
Closing, as this appears to be a bug in the user code and not in Node.js. The solution is to properly account for
byteOffsetwhen slicing from the underlying ArrayBuffer within the user'screateReadStreammethod. If this does not resolve the problem, please comment here and we will re-open and investigate further.lll000111 commentedon Aug 20, 2018
@jasnell
No there isn't, as I said, I have a cross-platform scenario with a lot of stuff around it. All stream modules are equal so that the main code can use one common stream interface, and I have to do the stupid string-based encoding stuff for React Native where binary streams are base64 strings.
When I change the zero to
byteOffsetnothing changes. When I remove the entire "if" and just use the buffer nothing changes.THAT IS A BUG IN NODE.JS
addaleax commentedon Aug 20, 2018
This fixes your code.
jasnell commentedon Aug 20, 2018
Relevant documentation: https://nodejs.org/dist/latest-v10.x/docs/api/buffer.html#buffer_buf_byteoffset
lll000111 commentedon Aug 20, 2018
@addaleax Indeed it does. However, something changed from 10.7.0 to 10.8.0 and I always read the changelog — there was nothing in it that seemed relevant...
addaleax commentedon Aug 20, 2018
@lll000111 I’m not sure – the relevant PR is the one linked above by @jasnell, #21968. It’s one of only two entries in the 10.8.0 changelog that target the
fssubsystem, and it’s not something that should typically affect users directly…jasnell commentedon Aug 20, 2018
lll000111 commentedon Aug 21, 2018
@jasnell Is that code about your earlier comment
Because I already said a few things about that. I can't use fancy node.js specific things.