88
99volatile int thread_started = 0 ;
1010volatile int enabled = 0 ;
11+ /* Set by the sampler thread while it takes and writes one sample. */
12+ static volatile LONG sampler_busy = 0 ;
1113#ifndef RPYTHON_VMPROF
1214static PY_WIN_THREAD_STATE * target_tstate = NULL ;
1315#endif
@@ -16,11 +18,25 @@ HANDLE write_mutex;
1618
1719int prepare_concurrent_bufs (void )
1820{
19- if (!(write_mutex = CreateMutex (NULL , FALSE, NULL )))
20- return -1 ;
21+ if (write_mutex == NULL ) {
22+ if (!(write_mutex = CreateMutex (NULL , FALSE, NULL )))
23+ return -1 ;
24+ }
2125 return 0 ;
2226}
2327
28+ /* Wait for the sampler thread to finish the sample it may be in the middle
29+ of. Callers clear `enabled` first so that no new sample starts; without
30+ this wait a stale sample could be written into the next profile, ahead of
31+ its header. */
32+ static void wait_for_sampler (void )
33+ {
34+ MemoryBarrier ();
35+ while (sampler_busy ) {
36+ SwitchToThread ();
37+ }
38+ }
39+
2440int vmprof_register_virtual_function (char * code_name , intptr_t code_uid ,
2541 int auto_retry )
2642{
@@ -126,8 +142,9 @@ int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_st
126142#else
127143 frame = PyThreadState_GetFrame (tstate );
128144#endif
145+ /* leave room for the thread id appended below */
129146 depth = vmp_walk_and_record_stack (frame , stack -> stack ,
130- MAX_STACK_DEPTH , 0 , 0 );
147+ MAX_STACK_DEPTH - 1 , 0 , 0 );
131148#ifdef _MSC_VER
132149 } __except (EXCEPTION_EXECUTE_HANDLER ) {
133150 depth = -1 ;
@@ -193,19 +210,25 @@ long __stdcall vmprof_mainloop(void *arg)
193210 // cpython version
194211 while (1 ) {
195212 Sleep (vmprof_get_profile_interval_usec () * 1000 );
213+ sampler_busy = 1 ;
214+ MemoryBarrier ();
196215 if (!enabled ) {
216+ sampler_busy = 0 ;
197217 continue ;
198218 }
199219 tstate = get_current_thread_state ();
200220 if (!tstate )
201221 tstate = target_tstate ;
202- if (!tstate )
222+ if (!tstate ) {
223+ sampler_busy = 0 ;
203224 continue ;
225+ }
204226 depth = vmprof_snapshot_thread (tstate -> thread_id , tstate , stack );
205227 if (depth > 0 ) {
206228 vmp_write_all ((char * )stack + offsetof(prof_stacktrace_s , marker ),
207229 SIZEOF_PROF_STACKTRACE + depth * sizeof (void * ));
208230 }
231+ sampler_busy = 0 ;
209232 }
210233#else
211234 // pypy version
@@ -255,10 +278,9 @@ int vmprof_enable(int memory, int native, int real_time)
255278RPY_EXTERN
256279int vmprof_disable (void )
257280{
258- char marker = MARKER_TRAILER ;
259- (void )vmp_write_time_now (MARKER_TRAILER );
260-
261281 enabled = 0 ;
282+ wait_for_sampler ();
283+ (void )vmp_write_time_now (MARKER_TRAILER );
262284#ifndef RPYTHON_VMPROF
263285 target_tstate = NULL ;
264286#endif
@@ -270,6 +292,9 @@ RPY_EXTERN
270292void vmprof_ignore_signals (int ignored )
271293{
272294 enabled = !ignored ;
295+ if (ignored ) {
296+ wait_for_sampler ();
297+ }
273298}
274299
275300int vmp_native_enable (void )
0 commit comments