version 1.109, 2015/11/24 22:45:44 |
version 1.110, 2015/11/24 23:01:51 |
|
|
|
|
/* |
/* |
* Get server create lock. If already held then server start is happening in |
* Get server create lock. If already held then server start is happening in |
* another client, so block until the lock is released and return -1 to |
* another client, so block until the lock is released and return -2 to |
* retry. Ignore other errors - just continue and start the server without the |
* retry. Return -1 on failure to continue and start the server anyway. |
* lock. |
|
*/ |
*/ |
int |
int |
client_get_lock(char *lockfile) |
client_get_lock(char *lockfile) |
{ |
{ |
int lockfd; |
int lockfd; |
|
|
|
log_debug("lock file is %s", lockfile); |
|
|
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) { |
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) { |
lockfd = open("/dev/null", O_WRONLY); |
log_debug("open failed: %s", strerror(errno)); |
if (lockfd == -1) |
return (-1); |
fatal("open failed"); |
|
return (lockfd); |
|
} |
} |
log_debug("lock file is %s", lockfile); |
|
|
|
if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { |
if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { |
log_debug("flock failed: %s", strerror(errno)); |
log_debug("flock failed: %s", strerror(errno)); |
|
|
while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR) |
while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR) |
/* nothing */; |
/* nothing */; |
close(lockfd); |
close(lockfd); |
return (-1); |
return (-2); |
} |
} |
log_debug("flock succeeded"); |
log_debug("flock succeeded"); |
|
|
|
|
|
|
if (!locked) { |
if (!locked) { |
xasprintf(&lockfile, "%s.lock", path); |
xasprintf(&lockfile, "%s.lock", path); |
if ((lockfd = client_get_lock(lockfile)) == -1) { |
if ((lockfd = client_get_lock(lockfile)) < 0) { |
log_debug("didn't get lock"); |
log_debug("didn't get lock (%d)", lockfd); |
|
|
free(lockfile); |
free(lockfile); |
goto retry; |
lockfile = NULL; |
|
|
|
if (lockfd == -2) |
|
goto retry; |
} |
} |
log_debug("got lock"); |
log_debug("got lock (%d)", lockfd); |
|
|
/* |
/* |
* Always retry at least once, even if we got the lock, |
* Always retry at least once, even if we got the lock, |
|
|
goto retry; |
goto retry; |
} |
} |
|
|
if (unlink(path) != 0 && errno != ENOENT) { |
if (lockfd >= 0 && unlink(path) != 0 && errno != ENOENT) { |
free(lockfile); |
free(lockfile); |
close(lockfd); |
close(lockfd); |
return (-1); |
return (-1); |
|
|
fd = server_start(base, lockfd, lockfile); |
fd = server_start(base, lockfd, lockfile); |
} |
} |
|
|
if (locked) { |
if (locked && lockfd >= 0) { |
free(lockfile); |
free(lockfile); |
close(lockfd); |
close(lockfd); |
} |
} |