-
Notifications
You must be signed in to change notification settings - Fork 7.3k
writestream should fsync(2) before close(2) #6438
Comments
That section of the man page only applies when the system crashes or powers down before the operating system gets a chance to flush the disk cache. It's highly unlikely that we'll change the default behavior but a patch that adds a 'fsyncOnClose' flag would be acceptable, I think. Should come with documentation, regression tests, etc. |
Are you sure about your interpretation of the man page? I don't think it reads that way. It's talking about a successful close. Anyway, I will take a look at adding the flag you describe. For now, I'm working around this issue by subscribing to the finish event on my read stream with a call to fs.fsyncSync(writeStream.fd) before I call pipe. This works, but it's obviously not pretty! |
On all the platforms that we support, the operating system's internal view of the file system (and therefore the view that's presented to user space) is always consistent unless there's been an interruption from outside, like a brownout. Of course, it's possible for disk controllers to lie about whether the data has actually been written to disk. But in that case, fsync() won't help either. |
OK. It's odd that calling fsync as described fixes this. It could definitely be the way the driver is implemented on this server hardware. One more quote from man 3 close:
I'm not sure when an async I/O operation is "cancelable", though. |
That's not really applicable to node.js. All file operations are synchronous but executed inside a thread pool. (Besides that, I don't think Windows AIO semantics quite follow POSIX AIO.) |
@polidore, you didn't actually say what problem you are having, or what fsync-before-close "fixed". If you are closing the stream, and then power cycling your machine, as Ben says, fsync "might" help you (you are still at mercy of lower layers of i/o stack, particular drive controllers). But if after successful close, another process on the same o/s is NOT seeing the file as having the state completely written... that would be weird. And most likely a race condition between your two processes, not an o/s or node bug. |
Sam, sorry if I wasn't clear. I'm doing something like this:
My file will not have been flushed properly. If i do:
It works properly. I also tried just waiting 10 seconds after I get 'close', and that doesn't work. It seems like the read stream finishes and instantly closes the write stream and something prevents the data from being written to disk. I'm using windows server 2008 with 64 bit node v0.10.20. I believe the drives are Hitachi SCSI drives. |
@bnoordhuis I didn't realize you weren't using the OS's async i/o. You're right, then, those comments from the man file aren't relevant. |
@polidore If the write callback is being fired before the write operation is completed, then I'd think that this is a bug lower in libuv, because the contract is for the write to have completed before calling the callback, which (as @bnoordhuis said) should always be guaranteed to be consistent unless there is a power outage. @piscisaureus @sblom Is this a windows specific bug? I've never seen this behavior on Unix, and I'm sure that it would have caused some npm problems by now if it was a general fs bug. Eg, note the streams3 regression that made npm virtually unusuable due to file truncation problems. npm does not tolerate file truncation well! (Which is correct, and a useful crisp failure mode, of course.) |
One thing to note- this stream is opened and then closed in potentially Thanks again for your attention here.
|
This is an issue also on MacOS and SmartOS. We have an issue were we are waiting for the 'close' event and do a Adding a sleep helped in our case, but we are not happy of course. adding this is on node: 0.10.30 on Windows 8 64 bit (ssd drives) and MacOS 10.9 and newest SmartOS release. |
I just stopped using streams and it worked fine with regular callbacks. On Friday, September 5, 2014, matthiasg notifications@github.com wrote:
|
What does that mean exactly just worked with callbacks ? Do you mean manually listening for data callbacks and calling write on that ? I have to say that the different events published by the different streams are quite confusing though. Some streams raise finish, some end, some close .. In what order ? Do all streams do that? Do even custom streams implementing eg writable stream do that ? That is in the sources of course, but the documentation is not straightforward and it does raise a number of questions and issues for consumers of streams.. Especially when they might not know about the exact stream type they are exposed to... Cheers -----Original Message----- I just stopped using streams and it worked fine with regular callbacks. On Friday, September 5, 2014, matthiasg notifications@github.com wrote:
|
@polidore I couldn't reproduce the issue you described, either on MacOS X or Windows 7. Here's the script I used:
The content of the file with the @matthiasg Do you have a small test case that reproduces your issue? Regarding the stream documentation, I would encourage you to create a separate issue. Thank you! |
@misterdjules i am having stream issues such as this: #8488. We were downloading zip files from a http server and it was quite difficult to get the implementation stable enough to consistently download and store the entire file on disk (without missing some bytes sometimes)... In the above case it is related to the interaction of http streams piped into filestreams. Still i would assume taking an http stream (downloading a binary) and piping that (using the official pipe method) into a fs.createWriteStream should NEVER leave files half finished without raising an error event (Unless the program or machine crashed of course). |
Closing this in favor of #8488 for lack of information and because it doesn't seem to be an issue for the original reporter. Please let us know if you think this issue is still relevant. |
@polidore could you explain what you mean by "stopped using streams and it worked fine with regular callbacks"? I think I'm having a similar issue here and still trying to figure out a workaround. thanks! |
Dito. It looks like we have a similar problem, too. Leads to this:
|
We use something like this for copying files now:
No errors anymore for us. |
I am having an issue where data piped to a fs.WriteStream isn't flushed to disk. I think this is because of the way WriteStream is implemented-- it just calls close(2) when it gets a finish event, but it should fsync first. If you look at the man pages for close, this bit is what I think is causing my problem:
On this line:
https://github.com/joyent/node/blob/master/lib/fs.js#L1610
It looks like the fs.writeStream calls close when it gets a finish from its source.
This is the function that will be called:
https://github.com/joyent/node/blob/master/lib/fs.js#L1542
And in this function, it is clear that node is calling fs.close (http://nodejs.org/api/fs.html#fs_fs_close_fd_callback) directly, which will cause the issue I describe above.
I think the response to the finish event should be changed to do an fsync first, then a close: http://nodejs.org/api/fs.html#fs_fs_fsync_fd_callback
I can put in a pull request for this, but I wanted to see if you guys agree with me first. This is only an issue for me on my production windows server, which has very large disk caches.
Thanks!
The text was updated successfully, but these errors were encountered: