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:
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user