Skip to content

Commit

Permalink
Merge pull request #1149 from MartinNowak/fix1149
Browse files Browse the repository at this point in the history
Failed to Lock when fetching lib
merged-on-behalf-of: Martin Nowak <code@dawg.eu>
  • Loading branch information
dlang-bot committed Jun 30, 2017
2 parents 8566bac + ea7e4fc commit 2af7481
Showing 1 changed file with 29 additions and 19 deletions.
48 changes: 29 additions & 19 deletions source/dub/internal/utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -45,32 +45,42 @@ Path getTempFile(string prefix, string extension = null)
return path;
}

// lockfile based on atomic mkdir
struct LockFile
/**
Obtain a lock for a file at the given path. If the file cannot be locked
within the given duration, an exception is thrown. The file will be created
if it does not yet exist. Deleting the file is not safe as another process
could create a new file with the same name.
The returned lock will get unlocked upon destruction.
Params:
path = path to file that gets locked
timeout = duration after which locking failed
Returns:
The locked file or an Exception on timeout.
*/
auto lockFile(string path, Duration timeout)
{
bool opCast(T:bool)() { return !!path; }
~this() { if (path) rmdir(path); }
string path;
}
import std.datetime, std.stdio : File;
import std.algorithm : move;

auto tryLockFile(string path)
{
import std.file;
if (collectException(mkdir(path)))
return LockFile(null);
return LockFile(path);
}
// Just a wrapper to hide (and destruct) the locked File.
static struct LockFile
{
// The Lock can't be unlinked as someone could try to lock an already
// opened fd while a new file with the same name gets created.
// Exclusive filesystem locks (O_EXCL, mkdir) could be deleted but
// aren't automatically freed when a process terminates, see #1149.
private File f;
}

auto lockFile(string path, Duration wait)
{
import std.datetime, std.file;
auto file = File(path, "w");
auto t0 = Clock.currTime();
auto dur = 1.msecs;
while (true)
{
if (!collectException(mkdir(path)))
return LockFile(path);
enforce(Clock.currTime() - t0 < wait, "Failed to lock '"~path~"'.");
if (file.tryLock())
return LockFile(move(file));
enforce(Clock.currTime() - t0 < timeout, "Failed to lock '"~path~"'.");
if (dur < 1024.msecs) // exponentially increase sleep time
dur *= 2;
Thread.sleep(dur);
Expand Down

0 comments on commit 2af7481

Please sign in to comment.