Closed Bug 1555644 Opened 5 years ago Closed 5 years ago

[*nix / macOS / Linux] OS.File should fall back to copy+delete if moving a file fails

Categories

(Toolkit :: Async Tooling, defect, P2)

defect

Tracking

()

RESOLVED FIXED
mozilla73
Tracking Status
firefox69 --- wontfix
firefox73 --- fixed

People

(Reporter: Gijs, Assigned: priyanksingh8, Mentored)

References

Details

(Whiteboard: [lang=js][good second bug])

Attachments

(2 files, 1 obsolete file)

In nsILocalFile, file moves fall back to using copy+delete if the move fails (see https://searchfox.org/mozilla-central/rev/7556a400affa9eb99e522d2d17c40689fa23a729/xpcom/io/nsLocalFileWin.cpp#1683-1719 and https://searchfox.org/mozilla-central/rev/7556a400affa9eb99e522d2d17c40689fa23a729/xpcom/io/nsLocalFileUnix.cpp#1000-1010 ), which can happen due to a variety of permission issues (e.g. bug 1549259, bug 1539881 - I believe there are others but they're tricky to find in bugzilla).

OS.File does not do this, and so it causes problems with downloads in a variety of circumstances. We should fix this.

Yoric, do you have cycles to work on this?

Flags: needinfo?(dteller)

I agree that it's needed but I doubt I have any cycles to work on this.

Willing to mentor and/or review, though.

Mentor: dteller
Flags: needinfo?(dteller)

Looks like the *nix implementation of nsILocalFile actually also needs to allow for copying in more situations than just EXDEV.

Blocks: 1521041
No longer blocks: 1549259
Whiteboard: [lang=js][good second bug]

The priority flag is not set for this bug.
:Yoric, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(dteller)
Flags: needinfo?(dteller)
Priority: -- → P2

Hi,
New to the community. I would be more than happy to contribute. Just set me with the necessary links and i will look into the bug.

Hi Amit,
Thanks for offering to help! Have you already downloaded and built the source code of Firefox?

Flags: needinfo?(amitraj.iitj)
Flags: needinfo?(amitraj.iitj)

Hey! what are the files associated with this bug. Can you please specify them here so that I can give them a look and try to solve the issue:)

Flags: needinfo?(dteller)

Hi David!
In the files that you mentioned above, you want to fall back to copy+delete only if the move operation fails or is there something else that you are looking for?

Flags: needinfo?(hamzah18051) → needinfo?(dteller)

(In reply to Hamzah Akhtar from comment #8)

Hi David!
In the files that you mentioned above, you want to fall back to copy+delete only if the move operation fails or is there something else that you are looking for?

That's pretty much it. If you look at the code, you'll see that we already do it in some handpicked cases. It seems we actually need to do it in all cases.

Flags: needinfo?(dteller)

Willing to work on this issue.

Flags: needinfo?(dteller)

Hey, Hamzah, what's your status?

Flags: needinfo?(dteller) → needinfo?(hamzah18051)

I'm currently caught up working on some other bug. Priyank, feel free to take up the issue.

Flags: needinfo?(hamzah18051)

Should I call the copy function and then File.remove function if move fails to fix the issue?

Flags: needinfo?(dteller)

Hey, Priyank, if you look at the source code I've linked in comment 7, you'll see the existing code. You'll see that we already have a fallback that pretty much calls copy then remove. We just need to make sure that it's always called in case of error, not just in a few cases.

Flags: needinfo?(dteller)

(In reply to David Teller [:Yoric] (please use "needinfo") from comment #14)

Hey, Priyank, if you look at the source code I've linked in comment 7, you'll see the existing code. You'll see that we already have a fallback that pretty much calls copy then remove. We just need to make sure that it's always called in case of error, not just in a few cases.

Can you please highlight the part where its already implement,
also how would I know whether and error has occurred does the file throw some kind of exception or something?

(In reply to Priyank Singh from comment #15)

Can you please highlight the part where its already implement,
also how would I know whether and error has occurred does the file throw some kind of exception or something?

*implemented

Priyank, have you already looked at the lines I've linked in comment 7?

Flags: needinfo?(priyanksingh8)

Yes.
Saw the complete File.Move function, unable to determine where the copy then remove procedure was implemented.
I guess WinFile.MoveFileEx is responsible for moving the file.

Flags: needinfo?(priyanksingh8)

So, let's start with the Unix version.

This code is the fallback. It is used to ensure that we copy & remove in case the move failed. For this version, we just need to make sure that we always use that fallback code if there was an error with the main code, not just in case of EXDEV.

For the Windows version, there's no fallback yet. We need to detect whether this call succeeded. If it failed, call File.copy and File.remove.

Flags: needinfo?(priyanksingh8)

Okay, saw the File.Move implementation for both unix and windows,
unix implementation always copies and then removes the file, and we need to invoke that functionality if there is some sort of error in main code, but what if there is no error in main code, how can we move the file without using File.copy and File.remove.

Also, we checked for EXDEV error apart from that what all errors main code could get which needs to be checked before moving the file.

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

(In reply to Priyank Singh from comment #20)

Okay, saw the File.Move implementation for both unix and windows,
unix implementation always copies and then removes the file, and we need to invoke that functionality if there is some sort of error in main code, but what if there is no error in main code, how can we move the file without using File.copy and File.remove.

No quite. The Unix implementation calls UnixFile.rename. If it succeeds (i.e. if it doesn't return -1), we stop there.

What we need now is basically to change line 726 to not check whether the error is EXDEV.

Also, we checked for EXDEV error apart from that what all errors main code could get which needs to be checked before moving the file.

I don't understand that sentence.

Flags: needinfo?(dteller) → needinfo?(priyanksingh8)

(In reply to David Teller [:Yoric] (please use "needinfo") from comment #21)

Also, we checked for EXDEV error apart from that what all errors main code could get which needs to be checked before moving the file.

I don't understand that sentence.
I meant how could we possibly detect that an error has occurred in main code, does it throws some exception?

What we need now is basically to change line 726 to not check whether the error is EXDEV.
Why do we need to do this?

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

(In reply to David Teller [:Yoric] (please use "needinfo") from comment #21)

Also, we checked for EXDEV error apart from that what all errors main code could get which needs to be checked before moving the file.

I don't understand that sentence.

I meant how could we possibly detect that an error has occurred in main code, does it throws some exception?

What we need now is basically to change line 726 to not check whether the error is EXDEV.

Why do we need to do this?

(In reply to Priyank Singh from comment #23)

(In reply to David Teller [:Yoric] (please use "needinfo") from comment #21)

Also, we checked for EXDEV error apart from that what all errors main code could get which needs to be checked before moving the file.

I don't understand that sentence.

I meant how could we possibly detect that an error has occurred in main code, does it throws some exception?

Functions from UnixFile follow the Unix conventions. It returns -1 in case of error, then we need to check the value of ctypes.errno to find out which error.

Functions from WinFile follow the Windows conventions. It returns 0 in case of error, then we need to check the value of ctypes.winLastError.

What we need now is basically to change line 726 to not check whether the error is EXDEV.

Why do we need to do this?

EXDEV is one specific Unix error that can show up in ctypes.errono. See http://man7.org/linux/man-pages/man3/errno.3.html for an (unfortunately incomplete) list of Unix errors.

Flags: needinfo?(dteller)
Flags: needinfo?(priyanksingh8)

Okay, so I must remove the check for EXDEV error so that our File.Move and File.remove would be called for all the cases whenever Unix.rename returns -1.

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

Well, it's File.copy and File.remove, but yeah, that's the idea.

Flags: needinfo?(dteller)

I had a look at windows implementation also, looks like throw_on_zero() function throws an error if the function WinFile.MoveFileEx returns zero.
So to have a fallback we must simply add File.copy and File.remove at the end of File.Move function.
Am I right?

Flags: needinfo?(dteller)

(In reply to Priyank Singh from comment #27)

I had a look at windows implementation also, looks like throw_on_zero() function throws an error if the function WinFile.MoveFileEx returns zero.
So to have a fallback we must simply add File.copy and File.remove at the end of File.Move function.
Am I right?

Well, you need to call File.copy and File.remove if WinFile.MoveFileEx fails.

Flags: needinfo?(dteller)
Flags: needinfo?(priyanksingh8)
Flags: needinfo?(priyanksingh8)
Assignee: nobody → priyanksingh8

Mmmh... Why did you upload two patches? One of them is probably wrong? Maybe you intended to upload the Unix version?

Flags: needinfo?(priyanksingh8)

I mistakingly committed my changes rather than amending it after I had sent my first patch for review. The second patch is just the continuation of the first one. I guess both the patches need to be merged.

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

Ok, could you merge them and resubmit?

If you're using hg, the most common way of doing this would be histedit tip^ and then choose roll for your latest patch.

Flags: needinfo?(dteller) → needinfo?(gijskruitbosch+bugs)

Fairly sure Yoric meant to needinfo Priyank...

Flags: needinfo?(gijskruitbosch+bugs) → needinfo?(priyanksingh8)

Can you provide me with more information as I don't know how to merge the patches.

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

That depends, are you using mercurial or git?

Flags: needinfo?(dteller) → needinfo?(priyanksingh8)

mercurial

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

In this case, if you have the fold extension installed, run

hg fold --from tip^

This will take your previous patch and your current patch and turn them into a single patch.

If you do not have the fold extension installed, you'll need to use histedit, so

hg histedit tip^

and choose roll for your latest patch. This will make it part of the previous patch.

Flags: needinfo?(dteller) → needinfo?(priyanksingh8)

But I haven't created another patch,
what I'd done previously was used hg commit --amend -m <I used the same message here>.
Therefore it didn't create another patch but the as the commit message was changed phabricator thought that it is another patch while I used --amend rather than creating another patch.

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

Well, that is odd.

In this case, in the "Add action" menu (in the bottom of phabricator), you should have access to an item "Abandon Revision" (if I recall correcty) that will let you remove this patch: https://phabricator.services.mozilla.com/D43211 .

Once this is done, don't forget to apply the changes I requested :)

Flags: needinfo?(dteller) → needinfo?(priyanksingh8)

Oh, looks like I forgot to click "Submit" with said requests when I wrote them. Sorry about that!

Attachment #9087655 - Attachment is obsolete: true
Attachment #9087673 - Attachment description: Bug 1555644 - Added fallback to call File.copy and File.remove function if MoveEx function fails → Bug 1555644 - Added fallback to call File.copy and File.remove function if moving function fails
Pushed by dteller@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/1091690427f2 Added fallback to call File.copy and File.remove function if moving function fails r=Yoric
Backout by malexandru@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/4411daffea4e Backed out changeset 1091690427f2 for causing browser-chrome failures. CLOSED TREE
Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

Ok, so a few errors to fix! I've left you new comments on Phabricator.

Flags: needinfo?(dteller) → needinfo?(priyanksingh8)
Attachment #9087673 - Attachment description: Bug 1555644 - Added fallback to call File.copy and File.remove function if moving function fails → Bug 1555644 - Added fallback to call File.copy and File.remove function if MoveEx function fails

Interesting. I see some errors:

"Win error 2 during operation copy on file C:\Users\task_1568812477\AppData\Local\Temp\test_osfile_async_copy_dest.tmp"

In the Windows version, maybe the call to File.copy has the wrong arguments? Could you double-check?

I checked the call, arguments are correct.
What if it is failing due to the previous patch which I had deleted.
Could you check if thats the issue?

Flags: needinfo?(priyanksingh8) → needinfo?(dteller)

If there's no problem with the call, it might be that the call to WinFile somehow succeeded at moving the file but returned non-0. Odd.

Flags: needinfo?(dteller)

Have you found the problem yet?
I observed that the build was failing in phabricator after I had deleted/abandoned the previous patch.
Could you check the complete code that is being pushed whether it is correct or not?

Flags: needinfo?(dteller)

I'm not sure yet what the issue is, but it's clearly not related to the previous patch.

Let's start by landing only the Unix version. We'll think about the Windows version later. Looking at the documentation of MoveFileEx ( https://msdn.microsoft.com/en-us/windows/aa365240(v=vs.80) ), I am starting to think that maybe MoveFileEx does everything we need already.

Flags: needinfo?(dteller) → needinfo?(priyanksingh8)

Yoric, looks like Priyank Singh has disappeared, can you resubmit the unix part to phab and land that, please? We keep getting bugs filed on this, cf. bug 1602306.

Flags: needinfo?(dteller)

I'll try and do that within the week.

Pushed by gijskruitbosch@gmail.com: https://hg.mozilla.org/integration/autoland/rev/e7deb2b7e09e If a file cannot be fast-renamed, copy it and remove the original;r=Gijs
Flags: needinfo?(dteller)
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla73
Flags: needinfo?(priyanksingh8)
Blocks: 1606741
Summary: OS.File should fall back to copy+delete if moving a file fails → [*nix / macOS / Linux] OS.File should fall back to copy+delete if moving a file fails
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: