file-dotlock.c revision ef5ad624ab2463cbbb58e7a616de9e6b191fcb3b
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2003 Timo Sirainen */
7ace5117d5f2395bd66f20b09e77dac05492f7ceTimo Sirainen/* 0.1 .. 0.2msec */
7ace5117d5f2395bd66f20b09e77dac05492f7ceTimo Sirainen#define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)rand() % 100000)
90cf976e328e093da91a8332d96182201f4ef6c1Timo Sirainenstatic pid_t read_local_pid(const char *lock_path)
90cf976e328e093da91a8332d96182201f4ef6c1Timo Sirainen /* read line */
90cf976e328e093da91a8332d96182201f4ef6c1Timo Sirainen /* fix the string */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* it should contain pid:host */
90cf976e328e093da91a8332d96182201f4ef6c1Timo Sirainen /* host must be ours */
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainenstatic int check_lock(time_t now, struct lock_info *lock_info)
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen i_error("lstat(%s) failed: %m", lock_info->lock_path);
24d7c5fc9fa1cb1f49402ec796654113199ba4e6Timo Sirainen /* either our first check or someone else got the lock file.
24d7c5fc9fa1cb1f49402ec796654113199ba4e6Timo Sirainen check if it contains a pid whose existence we can verify */
145d2eef238ed8bbff635e3b06951a83f0ee5a03Timo Sirainen lock_info->pid = read_local_pid(lock_info->lock_path);
24d7c5fc9fa1cb1f49402ec796654113199ba4e6Timo Sirainen /* we've local PID. Check if it exists. */
8759adc67109b5a12a7af3ed717c7040622a0a04Timo Sirainen if (kill(lock_info->pid, 0) == 0 || errno != ESRCH)
553308791c097219e8eb31cbd03a29e9e1333848Timo Sirainen /* doesn't exist - go ahead and delete */
24d7c5fc9fa1cb1f49402ec796654113199ba4e6Timo Sirainen if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen i_error("unlink(%s) failed: %m", lock_info->lock_path);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* see if the file we're locking is being modified */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* file doesn't exist. treat it as if
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen it hasn't changed */
8759adc67109b5a12a7af3ed717c7040622a0a04Timo Sirainen i_error("stat(%s) failed: %m", lock_info->path);
d31c77e63713a6cf3687a4b38ff8daf6d6c7a3ddTimo Sirainen } else if (lock_info->last_size != st.st_size ||
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen if (now > lock_info->last_change + (time_t)lock_info->stale_timeout) {
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen /* no changes for a while, assume stale lock */
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen i_error("unlink(%s) failed: %m", lock_info->lock_path);
7dcb5545370faa9d4ff83b3ede65a69fc3dd4b65Timo Sirainenstatic int try_create_lock(const char *lock_path, struct dotlock *dotlock_r)
cc0495b3bbe3c3e41c512274b302d6f0fa028187Timo Sirainen const char *str;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen fd = open(lock_path, O_WRONLY | O_EXCL | O_CREAT, 0644);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* write our pid and host, if possible */
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen str = t_strdup_printf("%s:%s", my_pid, my_hostname);
31a12066e4cd9310d64091c81b59fb8eb1986023Timo Sirainen /* failed, leave it empty then */
31a12066e4cd9310d64091c81b59fb8eb1986023Timo Sirainen i_error("ftruncate(%s) failed: %m", lock_path);
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen /* save the inode info after writing */
void *context),
const char *lock_path;
unsigned int stale_notify_threshold;
last_notify = 0;
unsigned int change_secs;
unsigned int wait_left;
context);
if (checkonly ||
const char *lock_path;