Skip to content

Commit b8916b7

Browse files
martinlsmMartin Lindström
andauthored
Arm backend: Fix incorrect lifetimes in executor runner (#16225) (#16339)
Keep `BufferDataLoader`, `Program`, `HierarchicalAllocator`, `MemoryManager` and a vector of spans alive for the full run by storing them in `RunnerContext` instead of local variables in `runner_init`. This solves a problem where these objects would go out of scope and therefore destruct when they where still needed, directly or indirectly, by the `Method` object created by `Program::load_method`. This can easily be verified by noting that `Method` holds a pointer to both the `Program` and the `MemoryManager`; thus, these objects must outlive the method. Fixes #16225 cc @freddan80 @per @zingo @oscarandersson8218 @digantdesai Signed-off-by: Martin Lindström <[email protected]> Co-authored-by: Martin Lindström <[email protected]>
1 parent 78c6b42 commit b8916b7

File tree

1 file changed

+34
-23
lines changed

1 file changed

+34
-23
lines changed

examples/arm/executor_runner/arm_executor_runner.cpp

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
#include <unistd.h>
9898
#include <memory>
9999
#include <type_traits>
100+
#include <utility>
100101
#include <vector>
101102

102103
#include "arm_memory_allocator.h"
@@ -340,6 +341,8 @@ void et_pal_free(ET_UNUSED void* ptr) {}
340341
namespace {
341342

342343
/// Lightweight heapless container that constructs and stores a T in-place.
344+
/// Useful when you want to avoid heap allocations but need to delay
345+
/// construction.
343346
template <typename T>
344347
class Box {
345348
public:
@@ -543,8 +546,13 @@ struct RunnerContext {
543546
size_t input_memsize = 0;
544547
size_t pte_size = 0;
545548
bool bundle_io = false;
549+
Box<BufferDataLoader> loader;
550+
Box<Program> program;
546551
Box<ArmMemoryAllocator> method_allocator;
547552
Box<ArmMemoryAllocator> temp_allocator;
553+
std::vector<Span<uint8_t>> planned_spans;
554+
Box<HierarchicalAllocator> planned_memory;
555+
Box<MemoryManager> memory_manager;
548556
Box<Result<Method>> method;
549557
#if defined(ET_EVENT_TRACER_ENABLED)
550558
Box<ETDumpGen> etdump_gen;
@@ -584,30 +592,31 @@ void runner_init(
584592
(unsigned int)status);
585593
}
586594
#endif
587-
auto loader = BufferDataLoader(program_data, ctx.program_data_len);
595+
ctx.loader.reset(program_data, ctx.program_data_len);
596+
auto& loader = ctx.loader.value();
588597
ET_LOG(Info, "PTE Model data loaded. Size: %zu bytes.", ctx.program_data_len);
589598

590599
// Parse the program file. This is immutable, and can also be reused
591600
// between multiple execution invocations across multiple threads.
592-
Result<Program> program = Program::load(&loader);
593-
if (!program.ok()) {
594-
ET_LOG(
595-
Info,
596-
"Program loading failed @ 0x%p: 0x%" PRIx32,
597-
program_data,
598-
program.error());
599-
}
601+
Result<Program> program_result = Program::load(&loader);
602+
ET_CHECK_MSG(
603+
program_result.ok(),
604+
"Program loading failed @ %p: 0x%" PRIx32,
605+
program_data,
606+
program_result.error());
607+
ctx.program.reset(std::move(program_result.get()));
608+
Program& program = ctx.program.value();
600609

601-
ET_LOG(Info, "Model buffer loaded, has %zu methods", program->num_methods());
610+
ET_LOG(Info, "Model buffer loaded, has %zu methods", program.num_methods());
602611

603612
{
604-
const auto method_name_result = program->get_method_name(0);
613+
const auto method_name_result = program.get_method_name(0);
605614
ET_CHECK_MSG(method_name_result.ok(), "Program has no methods");
606615
ctx.method_name = *method_name_result;
607616
}
608617
ET_LOG(Info, "Running method %s", ctx.method_name);
609618

610-
Result<MethodMeta> method_meta = program->method_meta(ctx.method_name);
619+
Result<MethodMeta> method_meta = program.method_meta(ctx.method_name);
611620
if (!method_meta.ok()) {
612621
ET_LOG(
613622
Info,
@@ -624,10 +633,9 @@ void runner_init(
624633
ctx.method_allocator.reset(
625634
method_allocation_pool_size, method_allocation_pool);
626635

627-
std::vector<uint8_t*> planned_buffers; // Owns the memory
628-
std::vector<Span<uint8_t>> planned_spans; // Passed to the allocator
636+
ctx.planned_spans.clear();
629637
size_t num_memory_planned_buffers = method_meta->num_memory_planned_buffers();
630-
638+
ctx.planned_spans.reserve(num_memory_planned_buffers);
631639
size_t planned_buffer_membase = ctx.method_allocator->used_size();
632640

633641
for (size_t id = 0; id < num_memory_planned_buffers; ++id) {
@@ -643,21 +651,24 @@ void runner_init(
643651
buffer != nullptr,
644652
"Could not allocate memory for memory planned buffer size %zu",
645653
buffer_size);
646-
planned_buffers.push_back(buffer);
647-
planned_spans.push_back({planned_buffers.back(), buffer_size});
654+
ctx.planned_spans.push_back({buffer, buffer_size});
648655
}
649656

650657
ctx.planned_buffer_memsize =
651658
ctx.method_allocator->used_size() - planned_buffer_membase;
652659

653-
HierarchicalAllocator planned_memory(
654-
{planned_spans.data(), planned_spans.size()});
660+
Span<Span<uint8_t>> planned_memory_span;
661+
if (!ctx.planned_spans.empty()) {
662+
planned_memory_span =
663+
Span<Span<uint8_t>>(ctx.planned_spans.data(), ctx.planned_spans.size());
664+
}
665+
ctx.planned_memory.reset(planned_memory_span);
655666

656667
ctx.temp_allocator.reset(temp_allocation_pool_size, temp_allocation_pool);
657668

658-
MemoryManager memory_manager(
669+
ctx.memory_manager.reset(
659670
&ctx.method_allocator.value(),
660-
&planned_memory,
671+
&ctx.planned_memory.value(),
661672
&ctx.temp_allocator.value());
662673

663674
size_t method_loaded_membase = ctx.method_allocator->used_size();
@@ -723,8 +734,8 @@ void runner_init(
723734
#endif // defined(ET_DUMP_INTERMEDIATE_OUTPUTS) || defined(ET_DUMP_OUTPUTS)
724735
#endif // defined(ET_EVENT_TRACER_ENABLED)
725736

726-
ctx.method.reset(
727-
program->load_method(ctx.method_name, &memory_manager, event_tracer_ptr));
737+
ctx.method.reset(program.load_method(
738+
ctx.method_name, &ctx.memory_manager.value(), event_tracer_ptr));
728739

729740
if (!ctx.method->ok()) {
730741
ET_LOG(

0 commit comments

Comments
 (0)