It used to be that if locking failed, lock_file() usually did not
register the lock_file object in lock_file_list but sometimes it did.
This confusion was compounded if lock_file() was called via
hold_lock_file_for_append(), which has its own failure modes.
The ambiguity didn't have any ill effects, because lock_file objects
cannot be removed from the lock_file_list anyway. But it is
unnecessary to leave this behavior inconsistent.
So change lock_file() to *always* ensure that the lock_file object is
registered in lock_file_list regardless of whether an error occurs.
Signed-off-by: Michael Haggerty <redacted>
---
lockfile.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/lockfile.c b/lockfile.c
index e78a35f..120a6d6 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -130,6 +130,22 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
*/
static const size_t max_path_len = sizeof(lk->filename) - 5;
+ if (!lock_file_list) {
+ /* One-time initialization */
+ sigchain_push_common(remove_lock_file_on_signal);
+ atexit(remove_lock_file);
+ }
+
+ if (!lk->on_list) {
+ /* Initialize *lk and add it to lock_file_list: */
+ lk->fd = -1;
+ lk->owner = 0;
+ lk->on_list = 1;
+ lk->filename[0] = 0;
+ lk->next = lock_file_list;
+ lock_file_list = lk;
+ }
+
if (strlen(path) >= max_path_len)
return -1;
strcpy(lk->filename, path);@@ -138,16 +154,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
strcat(lk->filename, ".lock");
lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 <= lk->fd) {
- if (!lock_file_list) {
- sigchain_push_common(remove_lock_file_on_signal);
- atexit(remove_lock_file);
- }
lk->owner = getpid();
- if (!lk->on_list) {
- lk->next = lock_file_list;
- lock_file_list = lk;
- lk->on_list = 1;
- }
if (adjust_shared_perm(lk->filename)) {
error("cannot fix permission bits on %s", lk->filename);
rollback_lock_file(lk);--
1.9.1