grep: allocate subrepos on heap

Currently, struct repository objects corresponding to submodules are
allocated on the stack in grep_submodule(). This currently works because
they will not be used once grep_submodule() exits, but a subsequent
patch will require these structs to be accessible for longer (perhaps
even in another thread). Allocate them on the heap and clear them only
at the very end.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Reviewed-by: Matheus Tavares <matheus.bernardino@usp.br>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jonathan Tan 2021-08-16 14:09:55 -07:00 committed by Junio C Hamano
parent 78ca584f1c
commit dd45471a37

View File

@ -65,6 +65,9 @@ static int todo_done;
/* Has all work items been added? */
static int all_work_added;
static struct repository **repos_to_free;
static size_t repos_to_free_nr, repos_to_free_alloc;
/* This lock protects all the variables above. */
static pthread_mutex_t grep_mutex;
@ -168,6 +171,19 @@ static void work_done(struct work_item *w)
grep_unlock();
}
static void free_repos(void)
{
int i;
for (i = 0; i < repos_to_free_nr; i++) {
repo_clear(repos_to_free[i]);
free(repos_to_free[i]);
}
FREE_AND_NULL(repos_to_free);
repos_to_free_nr = 0;
repos_to_free_alloc = 0;
}
static void *run(void *arg)
{
int hit = 0;
@ -415,19 +431,24 @@ static int grep_submodule(struct grep_opt *opt,
const struct object_id *oid,
const char *filename, const char *path, int cached)
{
struct repository subrepo;
struct repository *subrepo;
struct repository *superproject = opt->repo;
const struct submodule *sub;
struct grep_opt subopt;
int hit;
int hit = 0;
sub = submodule_from_path(superproject, null_oid(), path);
if (!is_submodule_active(superproject, path))
return 0;
if (repo_submodule_init(&subrepo, superproject, sub))
subrepo = xmalloc(sizeof(*subrepo));
if (repo_submodule_init(subrepo, superproject, sub)) {
free(subrepo);
return 0;
}
ALLOC_GROW(repos_to_free, repos_to_free_nr + 1, repos_to_free_alloc);
repos_to_free[repos_to_free_nr++] = subrepo;
/*
* NEEDSWORK: repo_read_gitmodules() might call
@ -438,7 +459,7 @@ static int grep_submodule(struct grep_opt *opt,
* subrepo's odbs to the in-memory alternates list.
*/
obj_read_lock();
repo_read_gitmodules(&subrepo, 0);
repo_read_gitmodules(subrepo, 0);
/*
* NEEDSWORK: This adds the submodule's object directory to the list of
@ -450,11 +471,11 @@ static int grep_submodule(struct grep_opt *opt,
* store is no longer global and instead is a member of the repository
* object.
*/
add_submodule_odb_by_path(subrepo.objects->odb->path);
add_submodule_odb_by_path(subrepo->objects->odb->path);
obj_read_unlock();
memcpy(&subopt, opt, sizeof(subopt));
subopt.repo = &subrepo;
subopt.repo = subrepo;
if (oid) {
enum object_type object_type;
@ -464,9 +485,9 @@ static int grep_submodule(struct grep_opt *opt,
struct strbuf base = STRBUF_INIT;
obj_read_lock();
object_type = oid_object_info(&subrepo, oid, NULL);
object_type = oid_object_info(subrepo, oid, NULL);
obj_read_unlock();
data = read_object_with_reference(&subrepo,
data = read_object_with_reference(subrepo,
oid, tree_type,
&size, NULL);
if (!data)
@ -484,7 +505,6 @@ static int grep_submodule(struct grep_opt *opt,
hit = grep_cache(&subopt, pathspec, cached);
}
repo_clear(&subrepo);
return hit;
}
@ -1182,5 +1202,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
run_pager(&opt, prefix);
clear_pathspec(&pathspec);
free_grep_patterns(&opt);
free_repos();
return !hit;
}