file-dotlock.c revision d6f2a39470b2d0b9e44bd886abacd41e6e1ec2d2
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi/* Copyright (C) 2003 Timo Sirainen */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi/* 0.1 .. 0.2msec */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi#define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)rand() % 100000)
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi const char *path, *lock_path, *temp_path;
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvistatic pid_t read_local_pid(const char *lock_path)
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* read line */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* fix the string */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* it should contain pid:host */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* host must be ours */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvistatic int check_lock(time_t now, struct lock_info *lock_info)
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi if (lstat(lock_info->lock_path, &st) < 0) {
796beea86bcdc92e4ba2f4865414a951b1717e5cTimo Sirainen i_error("lstat(%s) failed: %m", lock_info->lock_path);
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi if (lock_info->immediate_stale_timeout != 0 &&
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi now > st.st_mtime + (time_t)lock_info->immediate_stale_timeout &&
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi now > st.st_ctime + (time_t)lock_info->immediate_stale_timeout) {
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* old lock file */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi i_error("unlink(%s) failed: %m", lock_info->lock_path);
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* no change checking */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* either our first check or someone else got the lock file.
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi check if it contains a pid whose existence we can verify */
796beea86bcdc92e4ba2f4865414a951b1717e5cTimo Sirainen lock_info->pid = read_local_pid(lock_info->lock_path);
796beea86bcdc92e4ba2f4865414a951b1717e5cTimo Sirainen /* we've local PID. Check if it exists. */
796beea86bcdc92e4ba2f4865414a951b1717e5cTimo Sirainen if (kill(lock_info->pid, 0) == 0 || errno != ESRCH)
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* doesn't exist - go ahead and delete */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
796beea86bcdc92e4ba2f4865414a951b1717e5cTimo Sirainen i_error("unlink(%s) failed: %m", lock_info->lock_path);
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi /* file doesn't exist. treat it as if
796beea86bcdc92e4ba2f4865414a951b1717e5cTimo Sirainen it hasn't changed */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi i_error("stat(%s) failed: %m", lock_info->path);
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi } else if (lock_info->last_size != st.st_size ||
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi if (now > lock_info->last_change + (time_t)lock_info->stale_timeout) {
796beea86bcdc92e4ba2f4865414a951b1717e5cTimo Sirainen /* no changes for a while, assume stale lock */
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
b28403dc4da6ee942ff18315596b43d4c4e9b7bdMartti Rannanjärvi i_error("unlink(%s) failed: %m", lock_info->lock_path);
int fd;
return fd;
const char *str, *p;
if (p != NULL) {
unsigned int immediate_stale_timeout,
void *context),
void *context)
const char *lock_path;
unsigned int stale_notify_threshold;
if (do_wait) {
if (ret < 0)
if (checkonly)
if (ret != 0)
t_push();
t_pop();
if (ret == 0)
return ret;
unsigned int immediate_stale_timeout,
void *context),
return ret;
const char *lock_path;
unsigned int immediate_stale_timeout,
void *context),
void *context)
if (ret <= 0)
return fd;
const char *lock_path;
int old_errno;
if (verify_owner) {
if (verify_owner) {
int old_errno;