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 {
|
||||
struct BEd {
|
||||
internal::scripting::RubyState mrb;
|
||||
internal::trie::Trie<internal::functions::Function> functions;
|
||||
internal::functions::Function no_op;
|
||||
internal::functions::Function eof_op;
|
||||
@@ -24,9 +25,6 @@ struct BEd {
|
||||
internal::vase::AppendStorage append{"/tmp"};
|
||||
std::unordered_map<std::string, internal::buffer::Buffer *> buffers;
|
||||
|
||||
mrb_state *mrb = nullptr;
|
||||
int arena;
|
||||
|
||||
bool help_mode = false;
|
||||
bool prompt_mode = true;
|
||||
std::function<std::string(BEd &)> prompt = nullptr;
|
||||
|
||||
@@ -4,6 +4,30 @@
|
||||
#include "pch.h"
|
||||
|
||||
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 {
|
||||
mrb_state *mrb = nullptr;
|
||||
mrb_value proc = mrb_nil_value();
|
||||
|
||||
+1
-12
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace bed {
|
||||
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 file = "";
|
||||
bool suppress = false;
|
||||
@@ -42,11 +42,6 @@ BEd::BEd(std::vector<std::string> args)
|
||||
&& strcmp(colorterm, "24bit") != 0)
|
||||
color = false;
|
||||
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_extented(*this);
|
||||
internal::functions::Suffix::register_suffixes(*this);
|
||||
@@ -70,12 +65,6 @@ BEd::~BEd() {
|
||||
delete buffer;
|
||||
for (auto &[_, lang] : languages)
|
||||
delete lang;
|
||||
mrb->ud = nullptr;
|
||||
if (mrb) {
|
||||
mrb_gc_arena_restore(mrb, arena);
|
||||
mrb_full_gc(mrb);
|
||||
mrb_close(mrb);
|
||||
}
|
||||
}
|
||||
|
||||
void BEd::print_help() {
|
||||
|
||||
@@ -105,17 +105,18 @@ static mrb_value mrb_bed_unregister(mrb_state *mrb, mrb_value) {
|
||||
}
|
||||
|
||||
void register_basic(BEd &ctx) {
|
||||
auto mrb = ctx.mrb.state;
|
||||
auto *bed_error =
|
||||
mrb_define_class(ctx.mrb, "EdError", mrb_exc_get_id(ctx.mrb, MRB_ERROR_SYM(RuntimeError)));
|
||||
mrb_define_class(ctx.mrb, "FatalError", bed_error);
|
||||
mrb_define_method(ctx.mrb, ctx.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(ctx.mrb, ctx.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_class(mrb, "EdError", mrb_exc_get_id(mrb, MRB_ERROR_SYM(RuntimeError)));
|
||||
mrb_define_class(mrb, "FatalError", bed_error);
|
||||
mrb_define_method(mrb, mrb->kernel_module, "exit", mrb_bed_exit, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, mrb->kernel_module, "handle", mrb_bed_handle, MRB_ARGS_REQ(1));
|
||||
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(mrb, mrb->kernel_module, "unregister", mrb_bed_unregister, MRB_ARGS_REQ(1));
|
||||
}
|
||||
|
||||
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());
|
||||
if (!mrb->exc)
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user