Skip to content

Commit 573fcdd

Browse files
authored
Catch code object destruction (#145)
* Catch code object destruction for cpython
1 parent f3f520e commit 573fcdd

2 files changed

Lines changed: 56 additions & 1 deletion

File tree

src/scorepy/compat.hpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#pragma once
22

33
#include <array>
4+
#include <functional>
5+
#include <iostream>
46
#include <string_view>
57

68
#include <Python.h>
@@ -36,5 +38,47 @@ namespace compat
3638

3739
using PyCodeObject = PyCodeObject;
3840

41+
using destructor = destructor;
42+
using code_dealloc = std::add_pointer<void(PyCodeObject*)>::type; // void(*)(PyCodeObject*)
43+
44+
/**
45+
* @brief For CPython we need to make sure, that the we register our own dealloc function, so we
46+
* can handle the deleteion of code_objects in our code.
47+
*/
48+
struct RegisterCodeDealloc
49+
{
50+
RegisterCodeDealloc(std::function<void(PyCodeObject* co)> on_dealloc_fun)
51+
{
52+
external_on_dealloc_fun = on_dealloc_fun;
53+
// PyPy does not need this, as CodeObjects are compiled, and therefore live for the
54+
// programms lifetime
55+
#ifndef PYPY_VERSION
56+
if (!python_code_dealloc)
57+
{
58+
python_code_dealloc =
59+
reinterpret_cast<compat::code_dealloc>(PyCode_Type.tp_dealloc);
60+
PyCode_Type.tp_dealloc = reinterpret_cast<compat::destructor>(dealloc_fun);
61+
}
62+
else
63+
{
64+
std::cerr << "WARNING: Score-P Python's code_dealloc is alredy registerd!"
65+
<< std::endl;
66+
}
67+
#endif
68+
}
69+
70+
static void dealloc_fun(PyCodeObject* co)
71+
{
72+
if (external_on_dealloc_fun && python_code_dealloc)
73+
{
74+
external_on_dealloc_fun(co);
75+
python_code_dealloc(co);
76+
}
77+
}
78+
79+
inline static compat::code_dealloc python_code_dealloc;
80+
inline static std::function<void(PyCodeObject* co)> external_on_dealloc_fun;
81+
};
82+
3983
} // namespace compat
4084
} // namespace scorepy

src/scorepy/events.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <algorithm>
22
#include <array>
3-
#include <iostream>
43

54
#include <Python.h>
65

@@ -15,6 +14,18 @@ std::unordered_map<compat::PyCodeObject*, region_handle> regions;
1514
static std::unordered_map<std::string, region_handle> user_regions;
1615
static std::unordered_map<std::string, region_handle> rewind_regions;
1716

17+
/**
18+
* @brief when Python PyCodeObject is deallocated, remove it from our regions list.
19+
*
20+
* @param co code object to remove
21+
*/
22+
void on_dealloc(PyCodeObject* co)
23+
{
24+
regions.erase(co);
25+
}
26+
27+
static compat::RegisterCodeDealloc register_dealloc(on_dealloc);
28+
1829
// Used for regions, that have an identifier, aka a code object id. (instrumenter regions and
1930
// some decorated regions)
2031
void region_begin(std::string_view& function_name, std::string_view& module,

0 commit comments

Comments
 (0)