@@ -317,7 +317,9 @@ struct _zend_mm_heap {
317
317
} debug ;
318
318
};
319
319
#endif
320
+ #if ZEND_DEBUG
320
321
pid_t pid ;
322
+ #endif
321
323
zend_random_bytes_insecure_state rand_state ;
322
324
};
323
325
@@ -1310,15 +1312,20 @@ static zend_always_inline zend_mm_free_slot* zend_mm_encode_free_slot(const zend
1310
1312
#endif
1311
1313
}
1312
1314
1313
- static zend_always_inline zend_mm_free_slot * zend_mm_decode_free_slot ( zend_mm_heap * heap , zend_mm_free_slot * slot )
1315
+ static zend_always_inline zend_mm_free_slot * zend_mm_decode_free_slot_key ( uintptr_t shadow_key , zend_mm_free_slot * slot )
1314
1316
{
1315
1317
#ifdef WORDS_BIGENDIAN
1316
- return (zend_mm_free_slot * )((uintptr_t )slot ^ heap -> shadow_key );
1318
+ return (zend_mm_free_slot * )((uintptr_t )slot ^ shadow_key );
1317
1319
#else
1318
- return (zend_mm_free_slot * )(BSWAPPTR ((uintptr_t )slot ^ heap -> shadow_key ));
1320
+ return (zend_mm_free_slot * )(BSWAPPTR ((uintptr_t )slot ^ shadow_key ));
1319
1321
#endif
1320
1322
}
1321
1323
1324
+ static zend_always_inline zend_mm_free_slot * zend_mm_decode_free_slot (zend_mm_heap * heap , zend_mm_free_slot * slot )
1325
+ {
1326
+ return zend_mm_decode_free_slot_key (heap -> shadow_key , slot );
1327
+ }
1328
+
1322
1329
static zend_always_inline void zend_mm_set_next_free_slot (zend_mm_heap * heap , uint32_t bin_num , zend_mm_free_slot * slot , zend_mm_free_slot * next )
1323
1330
{
1324
1331
ZEND_ASSERT (bin_data_size [bin_num ] >= ZEND_MM_MIN_USEABLE_BIN_SIZE );
@@ -2027,6 +2034,34 @@ static void zend_mm_init_key(zend_mm_heap *heap)
2027
2034
zend_mm_refresh_key (heap );
2028
2035
}
2029
2036
2037
+ ZEND_API void zend_mm_refresh_key_child (zend_mm_heap * heap )
2038
+ {
2039
+ uintptr_t old_key = heap -> shadow_key ;
2040
+
2041
+ zend_mm_init_key (heap );
2042
+
2043
+ /* Update shadow pointers with new key */
2044
+ for (int i = 0 ; i < ZEND_MM_BINS ; i ++ ) {
2045
+ zend_mm_free_slot * slot = heap -> free_slot [i ];
2046
+ if (!slot ) {
2047
+ continue ;
2048
+ }
2049
+ zend_mm_free_slot * next ;
2050
+ while ((next = slot -> next_free_slot )) {
2051
+ zend_mm_free_slot * shadow = ZEND_MM_FREE_SLOT_PTR_SHADOW (slot , i );
2052
+ if (UNEXPECTED (next != zend_mm_decode_free_slot_key (old_key , shadow ))) {
2053
+ zend_mm_panic ("zend_mm_heap corrupted" );
2054
+ }
2055
+ zend_mm_set_next_free_slot (heap , i , slot , next );
2056
+ slot = next ;
2057
+ }
2058
+ }
2059
+
2060
+ #if ZEND_DEBUG
2061
+ heap -> pid = getpid ();
2062
+ #endif
2063
+ }
2064
+
2030
2065
static zend_mm_heap * zend_mm_init (void )
2031
2066
{
2032
2067
zend_mm_chunk * chunk = (zend_mm_chunk * )zend_mm_chunk_alloc_int (ZEND_MM_CHUNK_SIZE , ZEND_MM_CHUNK_SIZE );
@@ -2075,7 +2110,9 @@ static zend_mm_heap *zend_mm_init(void)
2075
2110
heap -> storage = NULL ;
2076
2111
#endif
2077
2112
heap -> huge_list = NULL ;
2113
+ #if ZEND_DEBUG
2078
2114
heap -> pid = getpid ();
2115
+ #endif
2079
2116
return heap ;
2080
2117
}
2081
2118
@@ -2535,13 +2572,12 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
2535
2572
p -> free_map [0 ] = (1L << ZEND_MM_FIRST_PAGE ) - 1 ;
2536
2573
p -> map [0 ] = ZEND_MM_LRUN (ZEND_MM_FIRST_PAGE );
2537
2574
2538
- pid_t pid = getpid ();
2539
- if (heap -> pid != pid ) {
2540
- zend_mm_init_key (heap );
2541
- heap -> pid = pid ;
2542
- } else {
2543
- zend_mm_refresh_key (heap );
2544
- }
2575
+ #if ZEND_DEBUG
2576
+ ZEND_ASSERT (getpid () == heap -> pid
2577
+ && "heap was re-used without calling zend_mm_refresh_key_child() after a fork" );
2578
+ #endif
2579
+
2580
+ zend_mm_refresh_key (heap );
2545
2581
}
2546
2582
}
2547
2583
@@ -2949,6 +2985,11 @@ ZEND_API void shutdown_memory_manager(bool silent, bool full_shutdown)
2949
2985
zend_mm_shutdown (AG (mm_heap ), full_shutdown , silent );
2950
2986
}
2951
2987
2988
+ ZEND_API void refresh_memory_manager (void )
2989
+ {
2990
+ zend_mm_refresh_key_child (AG (mm_heap ));
2991
+ }
2992
+
2952
2993
static ZEND_COLD ZEND_NORETURN void zend_out_of_memory (void )
2953
2994
{
2954
2995
fprintf (stderr , "Out of memory\n" );
@@ -3506,7 +3547,9 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
3506
3547
memcpy (storage -> data , data , data_size );
3507
3548
}
3508
3549
heap -> storage = storage ;
3550
+ #if ZEND_DEBUG
3509
3551
heap -> pid = getpid ();
3552
+ #endif
3510
3553
return heap ;
3511
3554
#else
3512
3555
return NULL ;
0 commit comments