1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-05 22:16:12 +02:00

lock_file(): always initialize and register lock_file object

The purpose of this change is to make the state diagram for
lock_file objects simpler and deterministic.

If locking fails, lock_file() sometimes leaves the lock_file object
partly initialized, but sometimes not. It sometimes registers the
object in lock_file_list, but sometimes not. This makes the state
diagram for lock_file objects effectively indeterministic and hard
to reason about. A future patch will also change the filename field
into a strbuf, which needs more involved initialization, so it will
become even more important that the state of a lock_file object is
well-defined after a failed attempt to lock.

The ambiguity doesn't currently have any ill effects, because
lock_file objects cannot be removed from the lock_file_list anyway.
But to make it easier to document and reason about the code, make
this behavior consistent: *always* initialize the lock_file object
and *always* register it in lock_file_list the first time it is
used, regardless of whether an error occurs.

While we're at it, make sure that all of the lock_file fields are
initialized to values appropriate for an unlocked object; the caller
is only responsible for making sure that on_list is set to zero before
the first time it is used.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Michael Haggerty 2014-10-01 12:28:13 +02:00 committed by Junio C Hamano
parent ebb8e380e9
commit 04e57d4d32

View File

@ -129,6 +129,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->filename[0] = 0;
lk->next = lock_file_list;
lock_file_list = lk;
lk->on_list = 1;
}
if (strlen(path) >= max_path_len) {
errno = ENAMETOOLONG;
return -1;
@ -139,16 +155,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)) {
int save_errno = errno;
error("cannot fix permission bits on %s",