Skip to content
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

Copying with preserveTimeStamps: true is inaccurate using 32bit node #269

Closed
CurryKitten opened this issue Sep 1, 2016 · 15 comments
Closed
Assignees
Milestone

Comments

@CurryKitten
Copy link

I have been running the fs-extra tests via npm test on various platforms, and have been getting failures on the 32bit versions of node. I wasn't sure if millisecond precision would be supported or not at 32bits, and it should be pointed out that the underlying OS is 64bit, but we do get back valid millisecond precision timestamps using 32bit node, it's just not accurate once we copy a file and ask to preserve timestamps.

This can be reproduced using this small snippet of code -

var fs = require('fs')
var fse = require('fs-extra')
var from = './forcopy' 
var to = './copied'

fse.copySync(from, to, {preserveTimestamps: true})
var fromStat = fs.statSync(from)
var toStat = fs.statSync(to)
console.log('From stat: ' , fromStat.mtime.getTime())
console.log('To stat: ' , toStat.mtime.getTime())

if I then touch the forcopy file and then run with 64bit node

$ which node
~/node-v4.5.0-linux-x64/bin/node
$ node copyTest
From stat:  1472712683269
To stat:  1472712683269

and then with 32bit node

$ which node
~/node-v4.5.0-linux-x86/bin/node
$ node copyTest
From stat:  1472712683269
To stat:  1472712683208

I can replicate this problem on rhel7, sles12 and ubuntu 14-04

@RyanZim
Copy link
Collaborator

RyanZim commented Oct 25, 2016

@jprichardson ?

@jprichardson
Copy link
Owner

@jprichardson ?

Ah, this could be a nasty one. Not sure how to proceed here as millisecond precision has been a bear.

@RyanZim
Copy link
Collaborator

RyanZim commented Oct 25, 2016

@CurryKitten Does this problem directly affect your actual code?

If not, this is low-priority or wontfix IMO.

@hhamilto
Copy link
Contributor

I did a little digging previously, and this issue is due to the limitations of floating point precision in 32 bit Node.js.

Internally, we implement the preserveTimestamps option by calling futimes on the new copy of the file. However, the interface for futimes that libuv exposes takes the timestamp as a double (and therefor does also Node.js) l, which limits the precision when running in 32 bit mode.

See here:
https://github.com/libuv/libuv/blob/v1.x/src/unix/fs.c#L154

As far as I can tell, we would need libuv to expose an alternate interface for futimes, and for node to then expose that interface to us.

@jprichardson
Copy link
Owner

Ah, sounds like maybe the best course of action is to throw up a warning if it's 32-bit and the flag is set.

@jprichardson
Copy link
Owner

Btw, thanks for your help here @hhamilto!

@RyanZim
Copy link
Collaborator

RyanZim commented Oct 25, 2016

@jprichardson How should we pass this warning? console.warn? (bad practice for libs IMO)

@jprichardson
Copy link
Owner

console.warn? (bad practice for libs IMO)

I generally agree with this, but I don't know of any other way other than console.warn....

@RyanZim
Copy link
Collaborator

RyanZim commented Oct 25, 2016

OK, sounds good.

Self-assigning but if someone else wants to do this, let me know.

@RyanZim RyanZim self-assigned this Oct 25, 2016
@RyanZim
Copy link
Collaborator

RyanZim commented Oct 25, 2016

@jprichardson What's the most accurate way to determine 32 or 64 bit?

@jprichardson
Copy link
Owner

jprichardson commented Oct 26, 2016

Since we care about the Node.js build arch not the actual CPU arch (i.e. 32 bit Node can run on 32-bit or 64-bit arch), I think process.arch should be fine.

@RyanZim
Copy link
Collaborator

RyanZim commented Oct 26, 2016

From the docs:

The current possible values are: 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', 'x64', and 'x86'.

I wasn't quite sure which architectures were 32 bit. Obviously arm, ia32, ppc, s390 are 32-bit, not quite sure about mips, mipsel, and the x* line (other than x64 being 64-bit).

@jprichardson
Copy link
Owner

Great point. I was naively only thinking about ia32.

@CurryKitten you were referring to ia32, correct? Or any 32-bit Node.js

@CurryKitten
Copy link
Author

@jprichardson I'm away on vacation at the moment, so don't have my notes with me - but I believe in this case it was just ia32 that exhibited this problem. From memory, zLinux31 was giving an issue, but it wasn't the same symptoms.

@RyanZim
Copy link
Collaborator

RyanZim commented Oct 26, 2016

OK, I think I'll just warn for ia32; if other architectures have the same problem, we can add warnings for them later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants