Skip to content

Commit e1a1eaa

Browse files
implausiblezawata
authored andcommitted
thread checkout: add locks around shared state
1 parent 07493cc commit e1a1eaa

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/checkout.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ typedef struct {
5353
git_buf tmp;
5454
} checkout_buffers;
5555

56+
enum {
57+
COMPLETED_STEPS_MUTEX_INITIALIZED = 1,
58+
PERFDATA_MUTEX_INITIALIZED = 2
59+
};
60+
5661
typedef struct {
5762
git_repository *repo;
5863
git_iterator *target;
@@ -77,6 +82,9 @@ typedef struct {
7782
git_checkout_perfdata perfdata;
7883
git_strmap *mkdir_map;
7984
git_attr_session attr_session;
85+
git_mutex completed_steps_mutex;
86+
git_mutex perfdata_mutex;
87+
unsigned int mutexes_initialized;
8088
} checkout_data;
8189

8290
typedef struct {
@@ -1430,9 +1438,11 @@ static int checkout_mkdir(
14301438
error = git_futils_mkdir_relative(
14311439
path, base, mode, flags, &mkdir_opts);
14321440

1441+
git_mutex_lock(&data->perfdata_mutex);
14331442
data->perfdata.mkdir_calls += mkdir_opts.perfdata.mkdir_calls;
14341443
data->perfdata.stat_calls += mkdir_opts.perfdata.stat_calls;
14351444
data->perfdata.chmod_calls += mkdir_opts.perfdata.chmod_calls;
1445+
git_mutex_unlock(&data->perfdata_mutex);
14361446

14371447
return error;
14381448
}
@@ -1452,7 +1462,9 @@ static int mkpath2file(
14521462
return error;
14531463

14541464
if (remove_existing) {
1465+
git_mutex_lock(&data->perfdata_mutex);
14551466
data->perfdata.stat_calls++;
1467+
git_mutex_unlock(&data->perfdata_mutex);
14561468

14571469
if (p_lstat(path, &st) == 0) {
14581470

@@ -1572,7 +1584,9 @@ static int blob_content_to_file(
15721584
return error;
15731585

15741586
if (st) {
1587+
git_mutex_lock(&data->perfdata_mutex);
15751588
data->perfdata.stat_calls++;
1589+
git_mutex_unlock(&data->perfdata_mutex);
15761590

15771591
if ((error = p_stat(path, st)) < 0) {
15781592
git_error_set(GIT_ERROR_OS, "failed to stat '%s'", path);
@@ -1608,7 +1622,9 @@ static int blob_content_to_link(
16081622
}
16091623

16101624
if (!error) {
1625+
git_mutex_lock(&data->perfdata_mutex);
16111626
data->perfdata.stat_calls++;
1627+
git_mutex_unlock(&data->perfdata_mutex);
16121628

16131629
if ((error = p_lstat(path, st)) < 0)
16141630
git_error_set(GIT_ERROR_CHECKOUT, "could not stat symlink %s", path);
@@ -1653,7 +1669,9 @@ static int checkout_submodule_update_index(
16531669
if (checkout_target_fullpath(&fullpath, data, file->path) < 0)
16541670
return -1;
16551671

1672+
git_mutex_lock(&data->perfdata_mutex);
16561673
data->perfdata.stat_calls++;
1674+
git_mutex_unlock(&data->perfdata_mutex);
16571675
if (p_stat(fullpath->ptr, &st) < 0) {
16581676
git_error_set(
16591677
GIT_ERROR_CHECKOUT, "could not stat submodule %s\n", file->path);
@@ -1721,7 +1739,9 @@ static int checkout_safe_for_update_only(
17211739
{
17221740
struct stat st;
17231741

1742+
git_mutex_lock(&data->perfdata_mutex);
17241743
data->perfdata.stat_calls++;
1744+
git_mutex_unlock(&data->perfdata_mutex);
17251745

17261746
if (p_lstat(path, &st) < 0) {
17271747
/* if doesn't exist, then no error and no update */
@@ -1834,7 +1854,9 @@ static int checkout_remove_the_old(
18341854
if (error < 0)
18351855
return error;
18361856

1857+
git_mutex_lock(&data->completed_steps_mutex);
18371858
data->completed_steps++;
1859+
git_mutex_unlock(&data->completed_steps_mutex);
18381860
report_progress(data, delta->old_file.path);
18391861

18401862
if ((actions[i] & CHECKOUT_ACTION__UPDATE_BLOB) == 0 &&
@@ -1851,7 +1873,10 @@ static int checkout_remove_the_old(
18511873
if (error < 0)
18521874
return error;
18531875

1876+
1877+
git_mutex_lock(&data->completed_steps_mutex);
18541878
data->completed_steps++;
1879+
git_mutex_unlock(&data->completed_steps_mutex);
18551880
report_progress(data, str);
18561881

18571882
if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0 &&
@@ -1889,7 +1914,9 @@ static int checkout_create_the_new_perform(
18891914
if ((error = checkout_blob(data, &delta->new_file)) < 0)
18901915
return error;
18911916

1917+
git_mutex_lock(&data->completed_steps_mutex);
18921918
data->completed_steps++;
1919+
git_mutex_unlock(&data->completed_steps_mutex);
18931920
report_progress(data, delta->new_file.path);
18941921
}
18951922

@@ -1932,7 +1959,9 @@ static int checkout_create_submodules(
19321959
if (error < 0)
19331960
return error;
19341961

1962+
git_mutex_lock(&data->completed_steps_mutex);
19351963
data->completed_steps++;
1964+
git_mutex_unlock(&data->completed_steps_mutex);
19361965
report_progress(data, delta->new_file.path);
19371966
}
19381967
}
@@ -2280,7 +2309,9 @@ static int checkout_create_conflicts(checkout_data *data)
22802309
if (error)
22812310
break;
22822311

2312+
git_mutex_lock(&data->completed_steps_mutex);
22832313
data->completed_steps++;
2314+
git_mutex_unlock(&data->completed_steps_mutex);
22842315
report_progress(data,
22852316
conflict->ours ? conflict->ours->path :
22862317
(conflict->theirs ? conflict->theirs->path : conflict->ancestor->path));
@@ -2298,7 +2329,9 @@ static int checkout_remove_conflicts(checkout_data *data)
22982329
if (git_index_conflict_remove(data->index, conflict) < 0)
22992330
return -1;
23002331

2332+
git_mutex_lock(&data->completed_steps_mutex);
23012333
data->completed_steps++;
2334+
git_mutex_unlock(&data->completed_steps_mutex);
23022335
}
23032336

23042337
return 0;
@@ -2375,6 +2408,12 @@ static void checkout_data_clear(checkout_data *data)
23752408
data->mkdir_map = NULL;
23762409

23772410
git_attr_session__free(&data->attr_session);
2411+
2412+
if (data->mutexes_initialized & COMPLETED_STEPS_MUTEX_INITIALIZED)
2413+
git_mutex_free(&data->completed_steps_mutex);
2414+
2415+
if (data->mutexes_initialized & PERFDATA_MUTEX_INITIALIZED)
2416+
git_mutex_free(&data->perfdata_mutex);
23782417
}
23792418

23802419
static int validate_target_directory(checkout_data *data)
@@ -2416,6 +2455,16 @@ static int checkout_data_init(
24162455
data->repo = repo;
24172456
data->target = target;
24182457

2458+
if ((error = git_mutex_init(&data->completed_steps_mutex)) < 0)
2459+
goto cleanup;
2460+
2461+
data->mutexes_initialized |= COMPLETED_STEPS_MUTEX_INITIALIZED;
2462+
2463+
if ((error = git_mutex_init(&data->perfdata_mutex)) < 0)
2464+
goto cleanup;
2465+
2466+
data->mutexes_initialized |= PERFDATA_MUTEX_INITIALIZED;
2467+
24192468
GIT_ERROR_CHECK_VERSION(
24202469
proposed, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options");
24212470

0 commit comments

Comments
 (0)