On Mon, Jun 15, 2020 at 11:49:33PM -0300, Ranier Vilela wrote: > I can confirm that the problem is in pgrename (dirmod.c), > something is not OK, with MoveFileEx, even with the > (MOVEFILE_REPLACE_EXISTING) flag. > > Replacing MoveFileEx, with > unlink (to); > rename (from, to); > > #if defined (WIN32) &&! defined (__ CYGWIN__) > unlink(to); > while (rename (from, to)! = 0) > #else > while (rename (from, to) <0) > #endif > > The log messages have disappeared. > > I suspect that if the target (to) file exists, MoveFileEx, it is failing to > rename, even with the flag enabled. > > Windows have the native rename function ( > https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rename-wrename?view=vs-2019 > ) > However, it fails if the target (to) file exists. > > Question, is it acceptable delete the target file, if it exists, to > guarantee the rename?
I don't think so - the idea behind writing $f.tmp and renaming it to $f is that it's *atomic*. I found an earlier thread addressing the same problem - we probably both should've found this earlier. https://commitfest.postgresql.org/27/2230/ https://www.postgresql.org/message-id/flat/CAPpHfds9trA6ipezK3BsuuOSQwEmESiqj8pkOxACFJpoLpcoNw%40mail.gmail.com#9b04576b717175e9dbf03cc991977d3f That thread goes back to 2017, so I don't think this is a new problem in v13. I'm not sure why you wouldn't also see the same behavior in v12. There's a couple patches in that thread, and the latest patch was rejected. Maybe you'd want to test them out and provide feedback. BTW, the first patch does: ! if (filePresent) ! { ! if (ReplaceFile(to, from, NULL, REPLACEFILE_IGNORE_MERGE_ERRORS, 0, 0)) ! break; ! } ! else ! { ! if (MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)) ! break; ! } Since it's racy to first check if the file exists, I would've thought we should instead do: ret = ReplaceFile() if ret == OK: break else if ret == FileDoesntExist: if MoveFileEx(): break Or, should we just try to create a file first, to allow ReplaceFile() to always work ? -- Justin