Skip to content

Commit dc4e588

Browse files
implausiblezawata
authored andcommitted
thread checkout: add locks around non thread-safe actions
1 parent e1a1eaa commit dc4e588

File tree

1 file changed

+49
-12
lines changed

1 file changed

+49
-12
lines changed

src/checkout.c

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ typedef struct {
5555

5656
enum {
5757
COMPLETED_STEPS_MUTEX_INITIALIZED = 1,
58-
PERFDATA_MUTEX_INITIALIZED = 2
58+
INDEX_MUTEX_INITIALIZED = 2,
59+
MKPATH_MUTEX_INITIALIZED = 4,
60+
PERFDATA_MUTEX_INITIALIZED = 8
5961
};
6062

6163
typedef struct {
@@ -83,6 +85,8 @@ typedef struct {
8385
git_strmap *mkdir_map;
8486
git_attr_session attr_session;
8587
git_mutex completed_steps_mutex;
88+
git_mutex index_mutex;
89+
git_mutex mkpath_mutex;
8690
git_mutex perfdata_mutex;
8791
unsigned int mutexes_initialized;
8892
} checkout_data;
@@ -1451,15 +1455,20 @@ static int mkpath2file(
14511455
checkout_data *data, const char *path, unsigned int mode)
14521456
{
14531457
struct stat st;
1454-
bool remove_existing = should_remove_existing(data);
1455-
unsigned int flags =
1458+
bool remove_existing;
1459+
unsigned int flags;
1460+
int error;
1461+
1462+
git_mutex_lock(&data->mkpath_mutex);
1463+
1464+
remove_existing = should_remove_existing(data);
1465+
flags =
14561466
(remove_existing ? MKDIR_REMOVE_EXISTING : MKDIR_NORMAL) |
14571467
GIT_MKDIR_SKIP_LAST;
1458-
int error;
14591468

14601469
if ((error = checkout_mkdir(
14611470
data, path, data->opts.target_directory, mode, flags)) < 0)
1462-
return error;
1471+
goto cleanup;
14631472

14641473
if (remove_existing) {
14651474
git_mutex_lock(&data->perfdata_mutex);
@@ -1476,12 +1485,14 @@ static int mkpath2file(
14761485
error = git_futils_rmdir_r(path, NULL, GIT_RMDIR_REMOVE_FILES);
14771486
} else if (errno != ENOENT) {
14781487
git_error_set(GIT_ERROR_OS, "failed to stat '%s'", path);
1479-
return GIT_EEXISTS;
1488+
error = GIT_EEXISTS;
14801489
} else {
14811490
git_error_clear();
14821491
}
14831492
}
14841493

1494+
cleanup:
1495+
git_mutex_unlock(&data->mkpath_mutex);
14851496
return error;
14861497
}
14871498

@@ -1557,12 +1568,19 @@ static int blob_content_to_file(
15571568
filter_session.attr_session = &data->attr_session;
15581569
filter_session.temp_buf = &buffers->tmp;
15591570

1560-
if (!data->opts.disable_filters &&
1561-
(error = git_filter_list__load(
1571+
if (!data->opts.disable_filters) {
1572+
git_mutex_lock(&data->index_mutex);
1573+
1574+
error = git_filter_list__load(
15621575
&fl, data->repo, blob, hint_path,
1563-
GIT_FILTER_TO_WORKTREE, &filter_session))) {
1564-
p_close(fd);
1565-
return error;
1576+
GIT_FILTER_TO_WORKTREE, &filter_session);
1577+
1578+
git_mutex_unlock(&data->index_mutex);
1579+
1580+
if (error) {
1581+
p_close(fd);
1582+
return error;
1583+
}
15661584
}
15671585

15681586
/* setup the writer */
@@ -1818,8 +1836,11 @@ static int checkout_blob(
18181836
data, &file->id, fullpath->ptr, file->path, file->mode, &st);
18191837

18201838
/* update the index unless prevented */
1821-
if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
1839+
if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0) {
1840+
git_mutex_lock(&data->index_mutex);
18221841
error = checkout_update_index(data, file, &st);
1842+
git_mutex_unlock(&data->index_mutex);
1843+
}
18231844

18241845
/* update the submodule data if this was a new .gitmodules file */
18251846
if (!error && strcmp(file->path, ".gitmodules") == 0)
@@ -2412,6 +2433,12 @@ static void checkout_data_clear(checkout_data *data)
24122433
if (data->mutexes_initialized & COMPLETED_STEPS_MUTEX_INITIALIZED)
24132434
git_mutex_free(&data->completed_steps_mutex);
24142435

2436+
if (data->mutexes_initialized & INDEX_MUTEX_INITIALIZED)
2437+
git_mutex_free(&data->index_mutex);
2438+
2439+
if (data->mutexes_initialized & MKPATH_MUTEX_INITIALIZED)
2440+
git_mutex_free(&data->mkpath_mutex);
2441+
24152442
if (data->mutexes_initialized & PERFDATA_MUTEX_INITIALIZED)
24162443
git_mutex_free(&data->perfdata_mutex);
24172444
}
@@ -2460,6 +2487,16 @@ static int checkout_data_init(
24602487

24612488
data->mutexes_initialized |= COMPLETED_STEPS_MUTEX_INITIALIZED;
24622489

2490+
if ((error = git_mutex_init(&data->index_mutex)) < 0)
2491+
goto cleanup;
2492+
2493+
data->mutexes_initialized |= INDEX_MUTEX_INITIALIZED;
2494+
2495+
if ((error = git_mutex_init(&data->mkpath_mutex)) < 0)
2496+
goto cleanup;
2497+
2498+
data->mutexes_initialized |= MKPATH_MUTEX_INITIALIZED;
2499+
24632500
if ((error = git_mutex_init(&data->perfdata_mutex)) < 0)
24642501
goto cleanup;
24652502

0 commit comments

Comments
 (0)