mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	gh-112367: Only free perf trampoline arenas at shutdown (#112368)
Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
This commit is contained in:
		
							parent
							
								
									bfb576ee23
								
							
						
					
					
						commit
						a73aa48e6b
					
				
					 4 changed files with 39 additions and 6 deletions
				
			
		| 
						 | 
					@ -101,6 +101,7 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *);
 | 
				
			||||||
extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
 | 
					extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
 | 
				
			||||||
extern int _PyPerfTrampoline_Init(int activate);
 | 
					extern int _PyPerfTrampoline_Init(int activate);
 | 
				
			||||||
extern int _PyPerfTrampoline_Fini(void);
 | 
					extern int _PyPerfTrampoline_Fini(void);
 | 
				
			||||||
 | 
					extern void _PyPerfTrampoline_FreeArenas(void);
 | 
				
			||||||
extern int _PyIsPerfTrampolineActive(void);
 | 
					extern int _PyIsPerfTrampolineActive(void);
 | 
				
			||||||
extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
 | 
					extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
 | 
				
			||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
					#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Avoid undefined behaviour when using the perf trampolines by not freeing the
 | 
				
			||||||
 | 
					code arenas until shutdown. Patch by Pablo Galindo
 | 
				
			||||||
| 
						 | 
					@ -216,10 +216,24 @@ perf_map_write_entry(void *state, const void *code_addr,
 | 
				
			||||||
    PyMem_RawFree(perf_map_entry);
 | 
					    PyMem_RawFree(perf_map_entry);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void*
 | 
				
			||||||
 | 
					perf_map_init_state(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PyUnstable_PerfMapState_Init();
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					perf_map_free_state(void *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PyUnstable_PerfMapState_Fini();
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_PyPerf_Callbacks _Py_perfmap_callbacks = {
 | 
					_PyPerf_Callbacks _Py_perfmap_callbacks = {
 | 
				
			||||||
    NULL,
 | 
					    &perf_map_init_state,
 | 
				
			||||||
    &perf_map_write_entry,
 | 
					    &perf_map_write_entry,
 | 
				
			||||||
    NULL,
 | 
					    &perf_map_free_state,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
| 
						 | 
					@ -415,7 +429,6 @@ _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks)
 | 
				
			||||||
    trampoline_api.write_state = callbacks->write_state;
 | 
					    trampoline_api.write_state = callbacks->write_state;
 | 
				
			||||||
    trampoline_api.free_state = callbacks->free_state;
 | 
					    trampoline_api.free_state = callbacks->free_state;
 | 
				
			||||||
    trampoline_api.state = NULL;
 | 
					    trampoline_api.state = NULL;
 | 
				
			||||||
    perf_status = PERF_STATUS_OK;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -434,6 +447,7 @@ _PyPerfTrampoline_Init(int activate)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!activate) {
 | 
					    if (!activate) {
 | 
				
			||||||
        tstate->interp->eval_frame = NULL;
 | 
					        tstate->interp->eval_frame = NULL;
 | 
				
			||||||
 | 
					        perf_status = PERF_STATUS_NO_INIT;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        tstate->interp->eval_frame = py_trampoline_evaluator;
 | 
					        tstate->interp->eval_frame = py_trampoline_evaluator;
 | 
				
			||||||
| 
						 | 
					@ -444,6 +458,9 @@ _PyPerfTrampoline_Init(int activate)
 | 
				
			||||||
        if (extra_code_index == -1) {
 | 
					        if (extra_code_index == -1) {
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (trampoline_api.state == NULL && trampoline_api.init_state != NULL) {
 | 
				
			||||||
 | 
					            trampoline_api.state = trampoline_api.init_state();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        perf_status = PERF_STATUS_OK;
 | 
					        perf_status = PERF_STATUS_OK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -454,16 +471,29 @@ int
 | 
				
			||||||
_PyPerfTrampoline_Fini(void)
 | 
					_PyPerfTrampoline_Fini(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
					#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
				
			||||||
 | 
					    if (perf_status != PERF_STATUS_OK) {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    PyThreadState *tstate = _PyThreadState_GET();
 | 
					    PyThreadState *tstate = _PyThreadState_GET();
 | 
				
			||||||
    if (tstate->interp->eval_frame == py_trampoline_evaluator) {
 | 
					    if (tstate->interp->eval_frame == py_trampoline_evaluator) {
 | 
				
			||||||
        tstate->interp->eval_frame = NULL;
 | 
					        tstate->interp->eval_frame = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    free_code_arenas();
 | 
					    if (perf_status == PERF_STATUS_OK) {
 | 
				
			||||||
 | 
					        trampoline_api.free_state(trampoline_api.state);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    extra_code_index = -1;
 | 
					    extra_code_index = -1;
 | 
				
			||||||
 | 
					    perf_status = PERF_STATUS_NO_INIT;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _PyPerfTrampoline_FreeArenas(void) {
 | 
				
			||||||
 | 
					#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
				
			||||||
 | 
					    free_code_arenas();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
 | 
					PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
 | 
				
			||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
					#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
				
			||||||
| 
						 | 
					@ -477,8 +507,8 @@ PyStatus
 | 
				
			||||||
_PyPerfTrampoline_AfterFork_Child(void)
 | 
					_PyPerfTrampoline_AfterFork_Child(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
					#ifdef PY_HAVE_PERF_TRAMPOLINE
 | 
				
			||||||
    PyUnstable_PerfMapState_Fini();
 | 
					 | 
				
			||||||
    if (persist_after_fork) {
 | 
					    if (persist_after_fork) {
 | 
				
			||||||
 | 
					        _PyPerfTrampoline_Fini();
 | 
				
			||||||
        char filename[256];
 | 
					        char filename[256];
 | 
				
			||||||
        pid_t parent_pid = getppid();
 | 
					        pid_t parent_pid = getppid();
 | 
				
			||||||
        snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
 | 
					        snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1797,6 +1797,7 @@ finalize_interp_clear(PyThreadState *tstate)
 | 
				
			||||||
        _PyArg_Fini();
 | 
					        _PyArg_Fini();
 | 
				
			||||||
        _Py_ClearFileSystemEncoding();
 | 
					        _Py_ClearFileSystemEncoding();
 | 
				
			||||||
        _PyPerfTrampoline_Fini();
 | 
					        _PyPerfTrampoline_Fini();
 | 
				
			||||||
 | 
					        _PyPerfTrampoline_FreeArenas();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    finalize_interp_types(tstate->interp);
 | 
					    finalize_interp_types(tstate->interp);
 | 
				
			||||||
| 
						 | 
					@ -1854,7 +1855,6 @@ Py_FinalizeEx(void)
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _PyAtExit_Call(tstate->interp);
 | 
					    _PyAtExit_Call(tstate->interp);
 | 
				
			||||||
    PyUnstable_PerfMapState_Fini();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Copy the core config, PyInterpreterState_Delete() free
 | 
					    /* Copy the core config, PyInterpreterState_Delete() free
 | 
				
			||||||
       the core config memory */
 | 
					       the core config memory */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue