@@ -1475,16 +1475,18 @@ void clear_delta_base_cache(void)
1475
1475
static void add_delta_base_cache (struct packed_git * p , off_t base_offset ,
1476
1476
void * base , unsigned long base_size , enum object_type type )
1477
1477
{
1478
- struct delta_base_cache_entry * ent = xmalloc ( sizeof ( * ent )) ;
1478
+ struct delta_base_cache_entry * ent ;
1479
1479
struct list_head * lru , * tmp ;
1480
1480
1481
1481
/*
1482
1482
* Check required to avoid redundant entries when more than one thread
1483
1483
* is unpacking the same object, in unpack_entry() (since its phases I
1484
1484
* and III might run concurrently across multiple threads).
1485
1485
*/
1486
- if (in_delta_base_cache (p , base_offset ))
1486
+ if (in_delta_base_cache (p , base_offset )) {
1487
+ free (base );
1487
1488
return ;
1489
+ }
1488
1490
1489
1491
delta_base_cached += base_size ;
1490
1492
@@ -1496,6 +1498,7 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
1496
1498
release_delta_base_cache (f );
1497
1499
}
1498
1500
1501
+ ent = xmalloc (sizeof (* ent ));
1499
1502
ent -> key .p = p ;
1500
1503
ent -> key .base_offset = base_offset ;
1501
1504
ent -> type = type ;
@@ -1776,12 +1779,10 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset,
1776
1779
void * external_base = NULL ;
1777
1780
unsigned long delta_size , base_size = size ;
1778
1781
int i ;
1782
+ off_t base_obj_offset = obj_offset ;
1779
1783
1780
1784
data = NULL ;
1781
1785
1782
- if (base )
1783
- add_delta_base_cache (p , obj_offset , base , base_size , type );
1784
-
1785
1786
if (!base ) {
1786
1787
/*
1787
1788
* We're probably in deep shit, but let's try to fetch
@@ -1819,24 +1820,33 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset,
1819
1820
"at offset %" PRIuMAX " from %s" ,
1820
1821
(uintmax_t )curpos , p -> pack_name );
1821
1822
data = NULL ;
1822
- free ( external_base );
1823
- continue ;
1824
- }
1823
+ } else {
1824
+ data = patch_delta ( base , base_size , delta_data ,
1825
+ delta_size , & size );
1825
1826
1826
- data = patch_delta (base , base_size ,
1827
- delta_data , delta_size ,
1828
- & size );
1827
+ /*
1828
+ * We could not apply the delta; warn the user, but
1829
+ * keep going. Our failure will be noticed either in
1830
+ * the next iteration of the loop, or if this is the
1831
+ * final delta, in the caller when we return NULL.
1832
+ * Those code paths will take care of making a more
1833
+ * explicit warning and retrying with another copy of
1834
+ * the object.
1835
+ */
1836
+ if (!data )
1837
+ error ("failed to apply delta" );
1838
+ }
1829
1839
1830
1840
/*
1831
- * We could not apply the delta; warn the user, but keep going.
1832
- * Our failure will be noticed either in the next iteration of
1833
- * the loop, or if this is the final delta, in the caller when
1834
- * we return NULL. Those code paths will take care of making
1835
- * a more explicit warning and retrying with another copy of
1836
- * the object .
1841
+ * We delay adding `base` to the cache until the end of the loop
1842
+ * because unpack_compressed_entry() momentarily releases the
1843
+ * obj_read_mutex, giving another thread the chance to access
1844
+ * the cache. Therefore, if `base` was already there, this other
1845
+ * thread could free() it (e.g. to make space for another entry)
1846
+ * before we are done using it .
1837
1847
*/
1838
- if (!data )
1839
- error ( "failed to apply delta" );
1848
+ if (!external_base )
1849
+ add_delta_base_cache ( p , base_obj_offset , base , base_size , type );
1840
1850
1841
1851
free (delta_data );
1842
1852
free (external_base );
0 commit comments