Hacker News new | ask | show | jobs
by rll 4984 days ago
This seems a bit oversimplified. Sure, there are no race conditions if there are no interactions between files, but if there are then swapping the symlink mid-request on requests that are already in progress will cause all sorts of race conditions.
1 comments

Not necessarily. On a Linux-based system, you're actually going to be operating on inodes rather than path names, so once you have a handle to a file, changing the path to it isn't going to affect your ability to interact with it. Just make sure that your new directory is set up so that the same request for the same target file ends up requesting the same inode and you shouldn't notice any problems.
"Just make sure that your new directory is set up so that the same request for the same target file ends up requesting the same inode"

If that is your goal, why do the mv at all?

...until your program needs to work with more than one file and the two are related in some way or opens 'the same file' twice.

For example, your compiler could fetch file X from the 'old' directory and file Y from the 'new' one, or your web server could log that it fetched file Z (which does not exist in the 'new' directory) to a log file in the 'new' directory.

It may be possible to mitigate this by requiring everybody to access all fils true a directory you opened atomically for them, but even if it is: good luck enforcing that rule, especially when using third party libraries.

But what if you don't have a handle to a file? Say you have index.php, which includes stuff.php. Order of operations:

  1. Server opens (old) index.php and begins executing
  2. Symlink swap
  3. Interpreter gets to the line that includes stuff.php, and then opens the *new* file
That's precisely why the classical PHP model is kinda stuffed under this situation.

If you want to stick with the traditional disc-read-per-request model, I'd be interested to see if something like a blue/green code deployment could work. You'd have two separate html roots - say, with /var/www/blue being current. You deploy your new code to /var/www/green, update httpd.conf to point there, then SIGHUP apache. The next deployment would switch back from /var/www/green to /var/www/blue. That way every request sees a consistent deployment from start to end.

If you use relative paths 3 will include old file. I'm not sure if that's a problem in PHP, but everything I used handled that fine.