@@ -537,7 +537,7 @@ st_numtable_increment(st_table *table, st_data_t key, size_t increment)
537537}
538538
539539void
540- stackprof_record_sample_for_stack (int num , uint64_t sample_timestamp , int64_t timestamp_delta )
540+ stackprof_record_sample_for_stack (int num , VALUE * frames_buffer , int * lines_buffer , uint64_t sample_timestamp , int64_t timestamp_delta )
541541{
542542 int i , n ;
543543 VALUE prev_frame = Qnil ;
@@ -571,8 +571,8 @@ stackprof_record_sample_for_stack(int num, uint64_t sample_timestamp, int64_t ti
571571 * in the raw buffer are stored in the opposite direction of stacks
572572 * in the frames buffer that came from Ruby. */
573573 for (i = num - 1 , n = 0 ; i >= 0 ; i -- , n ++ ) {
574- VALUE frame = _stackprof . frames_buffer [i ];
575- int line = _stackprof . lines_buffer [i ];
574+ VALUE frame = frames_buffer [i ];
575+ int line = lines_buffer [i ];
576576
577577 // Encode the line in to the upper 16 bits.
578578 uint64_t key = ((uint64_t )line << 48 ) | (uint64_t )frame ;
@@ -594,8 +594,8 @@ stackprof_record_sample_for_stack(int num, uint64_t sample_timestamp, int64_t ti
594594 _stackprof .raw_sample_index = _stackprof .raw_samples_len ;
595595 _stackprof .raw_samples [_stackprof .raw_samples_len ++ ] = (VALUE )num ;
596596 for (i = num - 1 ; i >= 0 ; i -- ) {
597- VALUE frame = _stackprof . frames_buffer [i ];
598- int line = _stackprof . lines_buffer [i ];
597+ VALUE frame = frames_buffer [i ];
598+ int line = lines_buffer [i ];
599599
600600 // Encode the line in to the upper 16 bits.
601601 uint64_t key = ((uint64_t )line << 48 ) | (uint64_t )frame ;
@@ -626,8 +626,8 @@ stackprof_record_sample_for_stack(int num, uint64_t sample_timestamp, int64_t ti
626626 }
627627
628628 for (i = 0 ; i < num ; i ++ ) {
629- int line = _stackprof . lines_buffer [i ];
630- VALUE frame = _stackprof . frames_buffer [i ];
629+ int line = lines_buffer [i ];
630+ VALUE frame = frames_buffer [i ];
631631 frame_data_t * frame_data = sample_for (frame );
632632
633633 if (frame_data -> seen_at_sample_number != _stackprof .overall_samples ) {
@@ -710,27 +710,28 @@ stackprof_record_gc_samples(void)
710710 for (i = 0 ; i < _stackprof .unrecorded_gc_samples ; i ++ ) {
711711 int64_t timestamp_delta = i == 0 ? delta_to_first_unrecorded_gc_sample : NUM2LONG (_stackprof .interval );
712712
713+ /* Use local arrays for GC frames to avoid a data race with the
714+ * signal handler, which can overwrite _stackprof.frames_buffer
715+ * via stackprof_buffer_sample/rb_profile_frames at any time. */
716+ VALUE gc_frames [2 ];
717+ int gc_lines [2 ] = {0 , 0 };
718+
713719 if (_stackprof .unrecorded_gc_marking_samples ) {
714- _stackprof .frames_buffer [0 ] = FAKE_FRAME_MARK ;
715- _stackprof .lines_buffer [0 ] = 0 ;
716- _stackprof .frames_buffer [1 ] = FAKE_FRAME_GC ;
717- _stackprof .lines_buffer [1 ] = 0 ;
720+ gc_frames [0 ] = FAKE_FRAME_MARK ;
721+ gc_frames [1 ] = FAKE_FRAME_GC ;
718722 _stackprof .unrecorded_gc_marking_samples -- ;
719723
720- stackprof_record_sample_for_stack (2 , start_timestamp , timestamp_delta );
724+ stackprof_record_sample_for_stack (2 , gc_frames , gc_lines , start_timestamp , timestamp_delta );
721725 } else if (_stackprof .unrecorded_gc_sweeping_samples ) {
722- _stackprof .frames_buffer [0 ] = FAKE_FRAME_SWEEP ;
723- _stackprof .lines_buffer [0 ] = 0 ;
724- _stackprof .frames_buffer [1 ] = FAKE_FRAME_GC ;
725- _stackprof .lines_buffer [1 ] = 0 ;
726+ gc_frames [0 ] = FAKE_FRAME_SWEEP ;
727+ gc_frames [1 ] = FAKE_FRAME_GC ;
726728
727729 _stackprof .unrecorded_gc_sweeping_samples -- ;
728730
729- stackprof_record_sample_for_stack (2 , start_timestamp , timestamp_delta );
731+ stackprof_record_sample_for_stack (2 , gc_frames , gc_lines , start_timestamp , timestamp_delta );
730732 } else {
731- _stackprof .frames_buffer [0 ] = FAKE_FRAME_GC ;
732- _stackprof .lines_buffer [0 ] = 0 ;
733- stackprof_record_sample_for_stack (1 , start_timestamp , timestamp_delta );
733+ gc_frames [0 ] = FAKE_FRAME_GC ;
734+ stackprof_record_sample_for_stack (1 , gc_frames , gc_lines , start_timestamp , timestamp_delta );
734735 }
735736 }
736737 _stackprof .during_gc += _stackprof .unrecorded_gc_samples ;
@@ -743,7 +744,7 @@ stackprof_record_gc_samples(void)
743744static void
744745stackprof_record_buffer (void )
745746{
746- stackprof_record_sample_for_stack (_stackprof .buffer_count , _stackprof .buffer_time .timestamp_usec , _stackprof .buffer_time .delta_usec );
747+ stackprof_record_sample_for_stack (_stackprof .buffer_count , _stackprof .frames_buffer , _stackprof . lines_buffer , _stackprof . buffer_time .timestamp_usec , _stackprof .buffer_time .delta_usec );
747748
748749 // reset the buffer
749750 _stackprof .buffer_count = 0 ;
0 commit comments