I have a Delphi 2006 app that writes to a file and then regularly renames it to a sequenced name, and creates a new one, i.e.
open file.dat
write a record to file.dat
close file.dat
...
open file.dat
write a record to file.dat
close file.dat
rename file.dat to file20110818123456.dat
create file.dat
open file.dat
write a record to file.dat
close file.dat
...
The problem is that occasionally the rename fails with Error 32 - The process cannot access the file because it is being used by another process
. I am checking that the destination of the rename doesn't exist. It's as if the close of the file after writing a record doesn't happen immediately. I added a loop in the rename procedure to sleep for a bit and try again up to 10 times but that doesn't help.
function RenameFileAtAllCosts (const OldFileID : TFilename ;
const NewFileID : TFilename ;
out ErrorCode : Integer) : boolean ;
const
MaxRenameAttempts = 10 ;
var
RenameAttempts : integer ;
begin
Result := FileExists (OldFileID) ;
if (Result = true) then
begin
if FileExists (NewFileID) then
begin
Result := DeleteFile (PChar (NewFileID)) ;
end ;
if (Result = true) then
begin
Result := (not FileExists (NewFileID)) ;
end ;
if (Result = true) then
begin
RenameAttempts := 0 ;
repeat
SysUtils.Sleep (50) ;
Result := RenameFile (OldFileID, NewFileID) ;
inc (RenameAttempts)
until (Result or (RenameAttempts >= MaxRenameAttempts)) ;
end ;
end ;
if (not Result) then
begin
ErrorCode := GetLastError ;
end ;
end ;
* ADDITIONAL INFO *
This is the ProcMon log of the relevant disk I/O, with the associated Pascal source or psuedo-code preceding each block
open file.dat
write a record to file.dat
close file.dat
5:45:27.1718325 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
5:45:27.1719739 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,208, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:27.1720475 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,208, Length: 28, Priority: Normal
5:45:27.1721403 PM APP.exe 1276 CloseFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS
if FileExists (NewFileID) then // before call to RenameFileAtAllCosts
begin
5:45:27.8630005 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
if DeleteFile (NewFileID) then // before call to RenameFileAtAllCosts
begin
5:45:27.8634050 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
Result := FileExists (OldFileID) ;
5:45:27.8640878 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
5:45:27.8641684 PM APP.exe 1276 QueryBasicInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS CreationTime: 2/08/2011 7:45:59 PM, LastAccessTime: 19/08/2011 4:25:33 PM, LastWriteTime: 19/08/2011 5:45:27 PM, ChangeTime: 19/08/2011 5:45:27 PM, FileAttributes: A
5:45:27.8641902 PM APP.exe 1276 CloseFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS
if FileExists (NewFileID) then
begin
5:45:27.8648698 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
if (Result = true) then
begin
Result := (not FileExists (NewFileID)) ;
end ;
5:45:27.8656780 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
RenameAttempts := 0 ;
repeat
SysUtils.Sleep (50) ;
Result := RenameFile (OldFileID, NewFileID) ;
inc (RenameAttempts)
until (Result or (RenameAttempts >= MaxRenameAttempts)) ;
5:45:27.9211195 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:27.9834427 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.0459285 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.1084086 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.1710646 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.2335139 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.2959037 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.3584062 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.4209304 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.4834629 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
open file.dat
write several records to file.dat
close file.dat
5:45:28.4899722 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
5:45:28.4901002 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,236, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4901636 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,236, Length: 28, Priority: Normal
5:45:28.4902365 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,264, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4903031 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,264, Length: 28, Priority: Normal
5:45:28.4903517 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,292, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4905200 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,292, Length: 28, Priority: Normal
5:45:28.4905917 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,320, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4906633 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,320, Length: 28, Priority: Normal
5:45:28.4907120 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,348, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4907747 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,348, Length: 28, Priority: Normal
5:45:28.4908214 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,376, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4908841 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,376, Length: 28, Priority: Normal
5:45:28.4909308 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,404, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4909929 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,404, Length: 28, Priority: Normal
5:45:28.4910396 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,432, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4911023 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,432, Length: 28, Priority: Normal
5:45:28.4911491 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,460, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4912118 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,460, Length: 28, Priority: Normal
5:45:28.4912578 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,488, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4913206 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,488, Length: 28, Priority: Normal
5:45:28.4913673 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,516, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4914300 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,516, Length: 28, Priority: Normal
5:45:28.4914761 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,544, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4915388 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,544, Length: 28, Priority: Normal
5:45:28.4915855 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,572, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4916482 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,572, Length: 28, Priority: Normal
5:45:28.4916936 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,600, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4917570 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,600, Length: 28, Priority: Normal
5:45:28.4918043 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,628, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4919003 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,628, Length: 28, Priority: Normal
5:45:28.4919483 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,656, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4920110 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,656, Length: 28, Priority: Normal
5:45:28.4920577 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,684, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4921205 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,684, Length: 28, Priority: Normal
5:45:28.4921672 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,712, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4922299 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,712, Length: 28, Priority: Normal
5:45:28.4922843 PM APP.exe 1276 CloseFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS
* UPDATE *
I think I have nailed it. I downloaded handle.exe and ran it. Process explorer always shows no handles matching APP.DAT, but the handle.exe utility showed a list of handles owned by PID 4 (System) with APP.DAT as the filename. What I hadn't mentioned in my OP was that the same app runs on another network machine in a secondary "monitor" mode where it doesn't write to the APP*.DAT files but only reads from them. The "aha!" moment was when I realised that the problem only occurred when the monitor app was also running, and that the handle leaks showed as belonging to the "System" process - which presumably created the handle when the file was opened from the network machine.
Occasionally the monitor app was denied access to the file (always with Error 998 - Invalid access to memory location - for some reason) and the error path did not close the handle. From that point on the primary instance of the app was still able to read and write the file APP.DAT but failed on the rename. Making sure the file was closed on the error seems to have fixed it.
The pointer to "handle.exe" was the key, along with the knowledge that I could still write to a file with another opened handle, but a rename would fail. Thanks to everyone for their contributions.
It would appear to me that the problem is not the destination file, but the source file... Make sure the handle is closed on the source file, that's where your problem will be.