Add basic locking to the git_odb structure We grab the lock while accessing the alternates list, ensuring that we only initialize it once for the given git_odb. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
diff --git a/src/odb.c b/src/odb.c
index 785d3fe..8a6be55 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -31,6 +31,8 @@
#include <stdio.h>
struct git_odb {
+ git_lck lock;
+
/** Path to the "objects" directory. */
char *objects_dir;
@@ -417,12 +419,21 @@ static int open_alternates(git_odb *db)
{
unsigned n = 0;
+ gitlck_lock(&db->lock);
+ if (db->alternates) {
+ gitlck_unlock(&db->lock);
+ return 1;
+ }
+
db->alternates = git__malloc(sizeof(*db->alternates) * (n + 1));
- if (!db->alternates)
- return GIT_ERROR;
+ if (!db->alternates) {
+ gitlck_unlock(&db->lock);
+ return -1;
+ }
db->alternates[n] = NULL;
- return GIT_SUCCESS;
+ gitlck_unlock(&db->lock);
+ return 0;
}
int git_odb_open(git_odb **out, const char *objects_dir)
@@ -438,6 +449,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
}
db->alternates = NULL;
+ gitlck_init(&db->lock);
*out = db;
return GIT_SUCCESS;
@@ -448,6 +460,8 @@ void git_odb_close(git_odb *db)
if (!db)
return;
+ gitlck_lock(&db->lock);
+
if (db->alternates) {
git_odb **alt;
for (alt = db->alternates; *alt; alt++)
@@ -456,6 +470,9 @@ void git_odb_close(git_odb *db)
}
free(db->objects_dir);
+
+ gitlck_unlock(&db->lock);
+ gitlck_free(&db->lock);
free(db);
}
@@ -469,7 +486,7 @@ attempt:
return GIT_SUCCESS;
if (!git_odb__read_loose(out, db, id))
return GIT_SUCCESS;
- if (!db->alternates && !open_alternates(db))
+ if (!open_alternates(db))
goto attempt;
out->data = NULL;