Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could DropBox interfere with DeleteFile()/rename()

Tags:

I had the following code which got executed every two minutes all day long:

int sucessfully_deleted = DeleteFile(dest_filename);

if (!sucessfully_deleted)
{
    // this never happens
}

rename(source_filename,dest_filename);

Once every several hours the rename() would fail with errno=13 (EACCES). The files involved were all sitting on a DropBox directory and I had a hunch that DropBox could be the cause. I figured that it might just be possible that the DeleteFile() function may return with a non-zero successfully_deleted but actually DropBox could still be busy doing some stuff in relation to the deletion that prevented rename() from succeeding. What I did next was to change rename() to my_rename() which would attempt a rename() and upon any failure would Sleep() for one second and try a second time. Sure enough that has worked perfectly ever since. What's more, I get a diagnostic message displaying first-attempt-failures every several hours. It has never failed on the second attempt.

So you could say that the problem is entirely solved... but I would like to understand what might be going on so as to better defend myself against any related DropBox issues in the future...

Really I would like to have a new super_delete() function which does not return until the file is properly deleted and finished with in all respects.

like image 476
Mick Avatar asked Oct 07 '18 09:10

Mick


2 Answers

under windows request to delete file really never delete file just. it mark it FCB (File Control Block) with special flag (FCB_STATE_DELETE_ON_CLOSE). real deletion will be only when the last file handle will be closed.

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.

also if exist section ( memory-mapped file ) open on file - file even can not be marked for delete. api call fail with STATUS_CANNOT_DELETE. so in general impossible always delete file.

in case exist another open handles for file (but not section !) begin from windows 10 rs1 exist new functional for delete - FileDispositionInformationEx with FILE_DISPOSITION_POSIX_SEMANTICS. in this case:

Normally a file marked for deletion is not actually deleted until all open handles for the file have been closed and the link count for the file is zero. When marking a file for deletion using FILE_DISPOSITION_POSIX_SEMANTICS, the link gets removed from the visible namespace as soon as the POSIX delete handle has been closed, but the file’s data streams remain accessible by other existing handles until the last handle has been closed.

ULONG DeletePosix(PCWSTR lpFileName)
{
    HANDLE hFile = CreateFileW(lpFileName, DELETE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 
        FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT, 0);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        return GetLastError();
    }

    static FILE_DISPOSITION_INFO_EX fdi = { FILE_DISPOSITION_DELETE| FILE_DISPOSITION_POSIX_SEMANTICS };

    ULONG dwError = SetFileInformationByHandle(hFile, FileDispositionInfoEx, &fdi, sizeof(fdi)) 
        ? NOERROR : GetLastError();

    // win10 rs1: file removed from parent folder here
    CloseHandle(hFile);

    return dwError;
}
like image 106
RbMm Avatar answered Nov 15 '22 01:11

RbMm


Update

Sorry i didn't get the question correctly the first time. I thought DeleteFile returned error 13.

Now I understand that DeleteFile succeeds but rename fails immediatlely after. It could be just a sync issue with the filesystem. After calling DeleteFile the file will be deleted when the OS commits the changes to the filesystem. That may not appen immediately. If you need to perform multiple operations to the same path, you should have a look at transactions https://docs.microsoft.com/it-it/windows/desktop/api/winbase/nf-winbase-deletefiletransacteda.

-- OLD ANSWER --

That is correct. If the another application handles to that file, DeleteFile will fail. Citing MSDN docs https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deletefile :

The DeleteFile function fails if an application attempts to delete a file that has other handles open for normal I/O or as a memory-mapped file (FILE_SHARE_DELETE must have been specified when other handles were opened).

This applies to dropbox, the antivirus, or in general, any other application that may open those files. Dropbox may open the file to compute its hash (to look for changes) at any moment. Same goes with the antivirus.

like image 41
Sergio Monteleone Avatar answered Nov 15 '22 00:11

Sergio Monteleone