Fixed the heap-use-after-free issue.

Just standard multithreading stuff; access to the allocator while hot
threads are running means stuff can change underneath us even /during/
a read.  I've mutex locked state for stuff in the drawing domain which
stops this issue.
This commit is contained in:
2025-12-12 04:29:32 +00:00
parent 5d78cb20df
commit a5666328b7
4 changed files with 12 additions and 4 deletions

View File

@@ -30,10 +30,14 @@ on the number line.
We already have the latest bound nodes so we're part-way through the We already have the latest bound nodes so we're part-way through the
tree. Just keep going down what we have so far surely? Even better, tree. Just keep going down what we have so far surely? Even better,
don't use nodes _at all_. Run with an index! don't use nodes _at all_. Run with an index!
** TODO Fix weird issue at past 100K nodes ** DONE Fix weird issue at past 100K nodes
std::vector seems to crap itself past 100K nodes - we keep getting std::vector seems to crap itself past 100K nodes - we keep getting
heap-use-after-free issues when trying to access the allocator nodes heap-use-after-free issues when trying to access the allocator nodes
at that point. Seemingly random. What's going on? at that point. Seemingly random. What's going on?
Solution: _everytime_ we want to access the allocator for nontrivial
(like memory reads) we need to lock the mutex. No two ways about it.
All draw functions were causing the issue.
** DONE Prettify code base ** DONE Prettify code base
It's a big blob of code currently in the graphics portion. Not very It's a big blob of code currently in the graphics portion. Not very
pretty but it gets the job done. Try modularisation. pretty but it gets the job done. Try modularisation.

View File

@@ -52,7 +52,7 @@ constexpr u64 clamp_to_width(const DrawState &ds, f64 val)
(val - ds.bounds.lower_val); (val - ds.bounds.lower_val);
} }
void draw_tree(const DrawState &ds, const State &state) void draw_tree(DrawState &ds, State &state)
{ {
// Number line // Number line
DrawLine(0, HEIGHT / 2, WIDTH, HEIGHT / 2, WHITE); DrawLine(0, HEIGHT / 2, WIDTH, HEIGHT / 2, WHITE);
@@ -63,6 +63,7 @@ void draw_tree(const DrawState &ds, const State &state)
DrawLine(lower_x, LINE_TOP, lower_x, LINE_BOTTOM, WHITE); DrawLine(lower_x, LINE_TOP, lower_x, LINE_BOTTOM, WHITE);
DrawLine(upper_x, LINE_TOP, upper_x, LINE_BOTTOM, WHITE); DrawLine(upper_x, LINE_TOP, upper_x, LINE_BOTTOM, WHITE);
state.mutex.lock();
std::stack<std::pair<u64, f64>> stack; std::stack<std::pair<u64, f64>> stack;
cw::node::Node n = state.allocator.get_val(0); cw::node::Node n = state.allocator.get_val(0);
stack.push(std::make_pair(0, n.value.norm)); stack.push(std::make_pair(0, n.value.norm));
@@ -87,6 +88,7 @@ void draw_tree(const DrawState &ds, const State &state)
stack.push(std::make_pair(n.right, right.value.norm)); stack.push(std::make_pair(n.right, right.value.norm));
} }
} }
state.mutex.unlock();
} }
using Clock = std::chrono::steady_clock; using Clock = std::chrono::steady_clock;

View File

@@ -12,6 +12,7 @@ namespace cw::state
{ {
void DrawState::compute_bounds() void DrawState::compute_bounds()
{ {
state.mutex.lock();
bounds.leftmost = state.allocator.get_val(0); bounds.leftmost = state.allocator.get_val(0);
while (bounds.leftmost.left >= 0) while (bounds.leftmost.left >= 0)
bounds.leftmost = state.allocator.get_val(bounds.leftmost.left); bounds.leftmost = state.allocator.get_val(bounds.leftmost.left);
@@ -19,6 +20,7 @@ namespace cw::state
bounds.rightmost = state.allocator.get_val(0); bounds.rightmost = state.allocator.get_val(0);
while (bounds.rightmost.right >= 0) while (bounds.rightmost.right >= 0)
bounds.rightmost = state.allocator.get_val(bounds.rightmost.right); bounds.rightmost = state.allocator.get_val(bounds.rightmost.right);
state.mutex.unlock();
bounds.lower_val = std::floorl(bounds.leftmost.value.norm); bounds.lower_val = std::floorl(bounds.leftmost.value.norm);
bounds.upper_val = std::ceill(bounds.rightmost.value.norm); bounds.upper_val = std::ceill(bounds.rightmost.value.norm);

View File

@@ -29,14 +29,14 @@ namespace cw::state
struct DrawState struct DrawState
{ {
const State &state; State &state;
struct Bounds struct Bounds
{ {
cw::node::Node leftmost, rightmost; cw::node::Node leftmost, rightmost;
f64 lower_val, upper_val; f64 lower_val, upper_val;
} bounds; } bounds;
DrawState(const State &state) : state{state} {}; DrawState(State &state) : state{state} {};
void compute_bounds(void); void compute_bounds(void);
}; };