Create backup file when writing new xml file?

Thiago Macieira thiago at macieira.org
Mon Feb 17 14:54:27 UTC 2014


Em seg 17 fev 2014, às 10:22:19, Linus Torvalds escreveu:
> You have two choices:
> 
>  - locking - either using flock or using a lock directory (and the
> really traditional and safe way really is to use a directory, because
> "O_CREAT | O_EXCL" is not necessarily actually reliable on NFS)

That's the "easy" way out. I'm wondering if there's something we could do that 
would avoid the lock file.

> 
>  - never actually use "unlink()", instead use "link()" to a unique
> name, and then you can unlink the original backup file. And then you
> can unlink the "backup of the backup" that is under the unique name
> *after* you've done everything else, so that you are never in the
> situation that two different processes could have unlinked things to
> the point where no backup exists.

Let me see if I understand:
 1) create temp file
 2) write data to it
 3) fsync
 4) link backup to backup^2
 5) rename $ORIG to backup 
 6) rename temp to $ORIG
 7) unlink backup^2

The $ORIG file name disappeared between 5 and 6. I was wondering if there's a 
way to prevent that. If I instead did:
 4bis) rename backup to backup^2 (ignoring ENOENT)
 5bis) link $ORIG to backup

In this sequence, there's no point at which $ORIG disappears.

However, if another process comes in and does the same, the link call will 
fail. I guess I could just repeat steps 4bis and 5bis, giving up after a few 
tries.

> Eventually (and it looks like it is going to be 3.15), on LInux we'll
> also have a new "rename2()" system call that takes an optional
> RENAME_NOREPLACE flag (and RENAME_EXCHANGE), which makes things like
> this easier.
> 
> But that will obviously be Linux-specific. Not that I know how well
> the whole hardlink model works under Windows.

I don't mind having Linux-specific calls that improve safety. We already do use 
pipe2, dup3, accept4, SOCK_CLOEXEC and O_CLOEXEC (though POSIX.1-2008 added 
this last one).

I haven't tested hardlinks on Windows, so I'll worry about it when I get to 
it. I know it's supported since Windows XP, but it occurs to me now that it's 
not supported on FAT filesystems. That's still a valid use-case, as in people 
saving files on USB sticks. Then again, link(2) would also fail on Linux for 
that case, so the handling needs to be done for all platforms anyway.

> There's no sane way to guarantee you won't have stale temporary files.
> You can minimize them with various tricks, but I don't think it's
> really worth worrying about.

Fair enough.

> For now, I'd suggest against playing games. Yes, you'll get temporary
> files if things crash. Try to be careful in the sequence that does
> this, so that you don't have operations that might cause problems, and
> don't call out to user code. Minimize the risk of crashes instead.

Everything is contained in one single function (QSaveFile::commit) and it does 
not call back out to user code.

However, that does not stop another thread from crashing the process or 
another process from trying to save to the same file at the same time. Or our 
making a mistake somewhere in the abstraction layers.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358



More information about the subsurface mailing list