file-dotlock.c revision ac67a027f8db99d0b65c656fe1e4f26261ae750f
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (C) 2003 Timo Sirainen */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen/* 0.1 .. 0.2msec */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)rand() % 100000)
1777c974563740daac427d3ef738903d8f6ad7d0Timo Sirainenstatic pid_t read_local_pid(const char *lock_path)
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* read line */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* fix the string */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* it should contain pid:host */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* host must be ours */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic int check_lock(time_t now, struct lock_info *lock_info)
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen i_error("lstat(%s) failed: %m", lock_info->lock_path);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen if (lock_info->immediate_stale_timeout != 0 &&
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen now > st.st_mtime + (time_t)lock_info->immediate_stale_timeout &&
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen now > st.st_ctime + (time_t)lock_info->immediate_stale_timeout) {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* old lock file */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen i_error("unlink(%s) failed: %m", lock_info->lock_path);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* no change checking */
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen /* either our first check or someone else got the lock file.
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen check if it contains a pid whose existence we can verify */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen lock_info->pid = read_local_pid(lock_info->lock_path);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* we've local PID. Check if it exists. */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (kill(lock_info->pid, 0) == 0 || errno != ESRCH)
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen /* doesn't exist - go ahead and delete */
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen i_error("unlink(%s) failed: %m", lock_info->lock_path);
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen /* file doesn't exist. treat it as if
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen it hasn't changed */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen i_error("stat(%s) failed: %m", lock_info->path);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen } else if (lock_info->last_size != st.st_size ||
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (now > lock_info->last_change + (time_t)lock_info->stale_timeout) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* no changes for a while, assume stale lock */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
916221f976af0ed8b397f06f4f381c0ac0be3b86Timo Sirainen i_error("unlink(%s) failed: %m", lock_info->lock_path);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenstatic int create_temp_file(const char *prefix, const char **path_r)
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;