2424#include "submodule.h"
2525#include "submodule-config.h"
2626#include "object-store.h"
27+ #include "packfile.h"
2728
2829static char const * const grep_usage [] = {
2930 N_ ("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]" ),
@@ -32,7 +33,6 @@ static char const * const grep_usage[] = {
3233
3334static int recurse_submodules ;
3435
35- #define GREP_NUM_THREADS_DEFAULT 8
3636static int num_threads ;
3737
3838static pthread_t * threads ;
@@ -91,18 +91,18 @@ static pthread_cond_t cond_result;
9191
9292static int skip_first_line ;
9393
94- static void add_work (struct grep_opt * opt , const struct grep_source * gs )
94+ static void add_work (struct grep_opt * opt , struct grep_source * gs )
9595{
96+ if (opt -> binary != GREP_BINARY_TEXT )
97+ grep_source_load_driver (gs , opt -> repo -> index );
98+
9699 grep_lock ();
97100
98101 while ((todo_end + 1 ) % ARRAY_SIZE (todo ) == todo_done ) {
99102 pthread_cond_wait (& cond_write , & grep_mutex );
100103 }
101104
102105 todo [todo_end ].source = * gs ;
103- if (opt -> binary != GREP_BINARY_TEXT )
104- grep_source_load_driver (& todo [todo_end ].source ,
105- opt -> repo -> index );
106106 todo [todo_end ].done = 0 ;
107107 strbuf_reset (& todo [todo_end ].out );
108108 todo_end = (todo_end + 1 ) % ARRAY_SIZE (todo );
@@ -200,12 +200,12 @@ static void start_threads(struct grep_opt *opt)
200200 int i ;
201201
202202 pthread_mutex_init (& grep_mutex , NULL );
203- pthread_mutex_init (& grep_read_mutex , NULL );
204203 pthread_mutex_init (& grep_attr_mutex , NULL );
205204 pthread_cond_init (& cond_add , NULL );
206205 pthread_cond_init (& cond_write , NULL );
207206 pthread_cond_init (& cond_result , NULL );
208207 grep_use_locks = 1 ;
208+ enable_obj_read_lock ();
209209
210210 for (i = 0 ; i < ARRAY_SIZE (todo ); i ++ ) {
211211 strbuf_init (& todo [i ].out , 0 );
@@ -257,12 +257,12 @@ static int wait_all(void)
257257 free (threads );
258258
259259 pthread_mutex_destroy (& grep_mutex );
260- pthread_mutex_destroy (& grep_read_mutex );
261260 pthread_mutex_destroy (& grep_attr_mutex );
262261 pthread_cond_destroy (& cond_add );
263262 pthread_cond_destroy (& cond_write );
264263 pthread_cond_destroy (& cond_result );
265264 grep_use_locks = 0 ;
265+ disable_obj_read_lock ();
266266
267267 return hit ;
268268}
@@ -295,16 +295,6 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
295295 return st ;
296296}
297297
298- static void * lock_and_read_oid_file (const struct object_id * oid , enum object_type * type , unsigned long * size )
299- {
300- void * data ;
301-
302- grep_read_lock ();
303- data = read_object_file (oid , type , size );
304- grep_read_unlock ();
305- return data ;
306- }
307-
308298static int grep_oid (struct grep_opt * opt , const struct object_id * oid ,
309299 const char * filename , int tree_name_len ,
310300 const char * path )
@@ -407,30 +397,28 @@ static int grep_submodule(struct grep_opt *opt,
407397{
408398 struct repository subrepo ;
409399 struct repository * superproject = opt -> repo ;
410- const struct submodule * sub = submodule_from_path (superproject ,
411- & null_oid , path );
400+ const struct submodule * sub ;
412401 struct grep_opt subopt ;
413402 int hit ;
414403
415- /*
416- * NEEDSWORK: submodules functions need to be protected because they
417- * access the object store via config_from_gitmodules(): the latter
418- * uses get_oid() which, for now, relies on the global the_repository
419- * object.
420- */
421- grep_read_lock ();
404+ sub = submodule_from_path (superproject , & null_oid , path );
422405
423- if (!is_submodule_active (superproject , path )) {
424- grep_read_unlock ();
406+ if (!is_submodule_active (superproject , path ))
425407 return 0 ;
426- }
427408
428- if (repo_submodule_init (& subrepo , superproject , sub )) {
429- grep_read_unlock ();
409+ if (repo_submodule_init (& subrepo , superproject , sub ))
430410 return 0 ;
431- }
432411
433- repo_read_gitmodules (& subrepo );
412+ /*
413+ * NEEDSWORK: repo_read_gitmodules() might call
414+ * add_to_alternates_memory() via config_from_gitmodules(). This
415+ * operation causes a race condition with concurrent object readings
416+ * performed by the worker threads. That's why we need obj_read_lock()
417+ * here. It should be removed once it's no longer necessary to add the
418+ * subrepo's odbs to the in-memory alternates list.
419+ */
420+ obj_read_lock ();
421+ repo_read_gitmodules (& subrepo , 0 );
434422
435423 /*
436424 * NEEDSWORK: This adds the submodule's object directory to the list of
@@ -443,7 +431,7 @@ static int grep_submodule(struct grep_opt *opt,
443431 * object.
444432 */
445433 add_to_alternates_memory (subrepo .objects -> odb -> path );
446- grep_read_unlock ();
434+ obj_read_unlock ();
447435
448436 memcpy (& subopt , opt , sizeof (subopt ));
449437 subopt .repo = & subrepo ;
@@ -455,14 +443,12 @@ static int grep_submodule(struct grep_opt *opt,
455443 unsigned long size ;
456444 struct strbuf base = STRBUF_INIT ;
457445
446+ obj_read_lock ();
458447 object = parse_object_or_die (oid , oid_to_hex (oid ));
459-
460- grep_read_lock ();
448+ obj_read_unlock ();
461449 data = read_object_with_reference (& subrepo ,
462450 & object -> oid , tree_type ,
463451 & size , NULL );
464- grep_read_unlock ();
465-
466452 if (!data )
467453 die (_ ("unable to read tree (%s)" ), oid_to_hex (& object -> oid ));
468454
@@ -587,7 +573,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
587573 void * data ;
588574 unsigned long size ;
589575
590- data = lock_and_read_oid_file (& entry .oid , & type , & size );
576+ data = read_object_file (& entry .oid , & type , & size );
591577 if (!data )
592578 die (_ ("unable to read tree (%s)" ),
593579 oid_to_hex (& entry .oid ));
@@ -625,12 +611,9 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
625611 struct strbuf base ;
626612 int hit , len ;
627613
628- grep_read_lock ();
629614 data = read_object_with_reference (opt -> repo ,
630615 & obj -> oid , tree_type ,
631616 & size , NULL );
632- grep_read_unlock ();
633-
634617 if (!data )
635618 die (_ ("unable to read tree (%s)" ), oid_to_hex (& obj -> oid ));
636619
@@ -659,13 +642,18 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
659642
660643 for (i = 0 ; i < nr ; i ++ ) {
661644 struct object * real_obj ;
645+
646+ obj_read_lock ();
662647 real_obj = deref_tag (opt -> repo , list -> objects [i ].item ,
663648 NULL , 0 );
649+ obj_read_unlock ();
664650
665651 /* load the gitmodules file for this rev */
666652 if (recurse_submodules ) {
667653 submodule_free (opt -> repo );
654+ obj_read_lock ();
668655 gitmodules_config_oid (& real_obj -> oid );
656+ obj_read_unlock ();
669657 }
670658 if (grep_object (opt , pathspec , real_obj , list -> objects [i ].name ,
671659 list -> objects [i ].path )) {
@@ -1065,7 +1053,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10651053 pathspec .recursive = 1 ;
10661054 pathspec .recurse_submodules = !!recurse_submodules ;
10671055
1068- if (list .nr || cached || show_in_pager ) {
1056+ if (recurse_submodules && untracked )
1057+ die (_ ("--untracked not supported with --recurse-submodules" ));
1058+
1059+ if (show_in_pager ) {
10691060 if (num_threads > 1 )
10701061 warning (_ ("invalid option combination, ignoring --threads" ));
10711062 num_threads = 1 ;
@@ -1075,7 +1066,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10751066 } else if (num_threads < 0 )
10761067 die (_ ("invalid number of threads specified (%d)" ), num_threads );
10771068 else if (num_threads == 0 )
1078- num_threads = HAVE_THREADS ? GREP_NUM_THREADS_DEFAULT : 1 ;
1069+ num_threads = HAVE_THREADS ? online_cpus () : 1 ;
10791070
10801071 if (num_threads > 1 ) {
10811072 if (!HAVE_THREADS )
@@ -1084,6 +1075,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10841075 && (opt .pre_context || opt .post_context ||
10851076 opt .file_break || opt .funcbody ))
10861077 skip_first_line = 1 ;
1078+
1079+ /*
1080+ * Pre-read gitmodules (if not read already) and force eager
1081+ * initialization of packed_git to prevent racy lazy
1082+ * reading/initialization once worker threads are started.
1083+ */
1084+ if (recurse_submodules )
1085+ repo_read_gitmodules (the_repository , 1 );
1086+ if (startup_info -> have_repository )
1087+ (void )get_packed_git (the_repository );
1088+
10871089 start_threads (& opt );
10881090 } else {
10891091 /*
@@ -1118,9 +1120,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11181120 }
11191121 }
11201122
1121- if (recurse_submodules && untracked )
1122- die (_ ("--untracked not supported with --recurse-submodules" ));
1123-
11241123 if (!show_in_pager && !opt .status_only )
11251124 setup_pager ();
11261125
0 commit comments