Make mruby raii cleanup, and fix cleanup bug.
- Functions were cleaned up after mruby, which was wrong. - Becuase functions could have stored a reference to a Block which refers to mruby. - And so it would crash on release builds at exit if custom functions were used.
This commit is contained in:
+1
-3
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
namespace bed {
|
namespace bed {
|
||||||
struct BEd {
|
struct BEd {
|
||||||
|
internal::scripting::RubyState mrb;
|
||||||
internal::trie::Trie<internal::functions::Function> functions;
|
internal::trie::Trie<internal::functions::Function> functions;
|
||||||
internal::functions::Function no_op;
|
internal::functions::Function no_op;
|
||||||
internal::functions::Function eof_op;
|
internal::functions::Function eof_op;
|
||||||
@@ -24,9 +25,6 @@ struct BEd {
|
|||||||
internal::vase::AppendStorage append{"/tmp"};
|
internal::vase::AppendStorage append{"/tmp"};
|
||||||
std::unordered_map<std::string, internal::buffer::Buffer *> buffers;
|
std::unordered_map<std::string, internal::buffer::Buffer *> buffers;
|
||||||
|
|
||||||
mrb_state *mrb = nullptr;
|
|
||||||
int arena;
|
|
||||||
|
|
||||||
bool help_mode = false;
|
bool help_mode = false;
|
||||||
bool prompt_mode = true;
|
bool prompt_mode = true;
|
||||||
std::function<std::string(BEd &)> prompt = nullptr;
|
std::function<std::string(BEd &)> prompt = nullptr;
|
||||||
|
|||||||
@@ -4,6 +4,30 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
namespace bed::internal::scripting {
|
namespace bed::internal::scripting {
|
||||||
|
struct RubyState {
|
||||||
|
mrb_state *state = nullptr;
|
||||||
|
int arena = 0;
|
||||||
|
|
||||||
|
explicit RubyState(BEd *ctx) : state(mrb_open()) {
|
||||||
|
if (!state)
|
||||||
|
throw fatal_error("Failed to initialize mruby.", 1);
|
||||||
|
state->ud = ctx;
|
||||||
|
arena = mrb_gc_arena_save(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
~RubyState() {
|
||||||
|
state->ud = nullptr;
|
||||||
|
if (state) {
|
||||||
|
mrb_gc_arena_restore(state, arena);
|
||||||
|
mrb_full_gc(state);
|
||||||
|
mrb_close(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RubyState(const RubyState &) = delete;
|
||||||
|
RubyState &operator=(const RubyState &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
struct Block {
|
struct Block {
|
||||||
mrb_state *mrb = nullptr;
|
mrb_state *mrb = nullptr;
|
||||||
mrb_value proc = mrb_nil_value();
|
mrb_value proc = mrb_nil_value();
|
||||||
|
|||||||
+1
-12
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace bed {
|
namespace bed {
|
||||||
BEd::BEd(std::vector<std::string> args)
|
BEd::BEd(std::vector<std::string> args)
|
||||||
: theme(internal::theme::Theme::default_theme()), io(*this) {
|
: mrb(this), theme(internal::theme::Theme::default_theme()), io(*this) {
|
||||||
std::string prompt_ = "";
|
std::string prompt_ = "";
|
||||||
std::string file = "";
|
std::string file = "";
|
||||||
bool suppress = false;
|
bool suppress = false;
|
||||||
@@ -42,11 +42,6 @@ BEd::BEd(std::vector<std::string> args)
|
|||||||
&& strcmp(colorterm, "24bit") != 0)
|
&& strcmp(colorterm, "24bit") != 0)
|
||||||
color = false;
|
color = false;
|
||||||
color_mode = color;
|
color_mode = color;
|
||||||
mrb = mrb_open();
|
|
||||||
if (!mrb)
|
|
||||||
throw fatal_error("Failed to initialize mruby.", 1);
|
|
||||||
mrb->ud = this;
|
|
||||||
arena = mrb_gc_arena_save(mrb);
|
|
||||||
internal::functions::Function::register_posix(*this);
|
internal::functions::Function::register_posix(*this);
|
||||||
internal::functions::Function::register_extented(*this);
|
internal::functions::Function::register_extented(*this);
|
||||||
internal::functions::Suffix::register_suffixes(*this);
|
internal::functions::Suffix::register_suffixes(*this);
|
||||||
@@ -70,12 +65,6 @@ BEd::~BEd() {
|
|||||||
delete buffer;
|
delete buffer;
|
||||||
for (auto &[_, lang] : languages)
|
for (auto &[_, lang] : languages)
|
||||||
delete lang;
|
delete lang;
|
||||||
mrb->ud = nullptr;
|
|
||||||
if (mrb) {
|
|
||||||
mrb_gc_arena_restore(mrb, arena);
|
|
||||||
mrb_full_gc(mrb);
|
|
||||||
mrb_close(mrb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BEd::print_help() {
|
void BEd::print_help() {
|
||||||
|
|||||||
@@ -105,17 +105,18 @@ static mrb_value mrb_bed_unregister(mrb_state *mrb, mrb_value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void register_basic(BEd &ctx) {
|
void register_basic(BEd &ctx) {
|
||||||
|
auto mrb = ctx.mrb.state;
|
||||||
auto *bed_error =
|
auto *bed_error =
|
||||||
mrb_define_class(ctx.mrb, "EdError", mrb_exc_get_id(ctx.mrb, MRB_ERROR_SYM(RuntimeError)));
|
mrb_define_class(mrb, "EdError", mrb_exc_get_id(mrb, MRB_ERROR_SYM(RuntimeError)));
|
||||||
mrb_define_class(ctx.mrb, "FatalError", bed_error);
|
mrb_define_class(mrb, "FatalError", bed_error);
|
||||||
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "exit", mrb_bed_exit, MRB_ARGS_NONE());
|
mrb_define_method(mrb, mrb->kernel_module, "exit", mrb_bed_exit, MRB_ARGS_NONE());
|
||||||
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "handle", mrb_bed_handle, MRB_ARGS_REQ(1));
|
mrb_define_method(mrb, mrb->kernel_module, "handle", mrb_bed_handle, MRB_ARGS_REQ(1));
|
||||||
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "register", mrb_bed_register, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
|
mrb_define_method(mrb, mrb->kernel_module, "register", mrb_bed_register, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
|
||||||
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "unregister", mrb_bed_unregister, MRB_ARGS_REQ(1));
|
mrb_define_method(mrb, mrb->kernel_module, "unregister", mrb_bed_unregister, MRB_ARGS_REQ(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(BEd &ctx, const std::string &str) {
|
void run(BEd &ctx, const std::string &str) {
|
||||||
mrb_state *mrb = ctx.mrb;
|
mrb_state *mrb = ctx.mrb.state;
|
||||||
mrb_load_nstring(mrb, str.data(), str.size());
|
mrb_load_nstring(mrb, str.data(), str.size());
|
||||||
if (!mrb->exc)
|
if (!mrb->exc)
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user