From c340c2abec6ce8ce9f82d4e5a1fac7cc24950089 Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 23 Mar 2018 23:39:46 +0000 Subject: [PATCH] Fix segfault on exit By ensuring duk_context is disposed last in ScriptEngine --- src/openrct2/scripting/ScriptEngine.cpp | 27 ++++++++++++++----------- src/openrct2/scripting/ScriptEngine.h | 20 ++++++++++++++++-- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index 2e5a142f4e..82ba255bf3 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -31,6 +31,20 @@ using namespace OpenRCT2::Scripting; static std::string Stringify(duk_context * ctx, duk_idx_t idx); +DukContext::DukContext() +{ + _context = duk_create_heap_default(); + if (_context == nullptr) + { + throw std::runtime_error("Unable to initialise duktape context."); + } +} + +DukContext::~DukContext() +{ + duk_destroy_heap(_context); +} + ScriptEngine::ScriptEngine(InteractiveConsole& console, IPlatformEnvironment& env) : _console(console), _env(env), @@ -38,20 +52,9 @@ ScriptEngine::ScriptEngine(InteractiveConsole& console, IPlatformEnvironment& en { } -ScriptEngine::~ScriptEngine() -{ - duk_destroy_heap(_context); -} - void ScriptEngine::Initialise() { - _context = duk_create_heap_default(); - if (_context == nullptr) - { - throw std::runtime_error("Unable to initialise duktape context."); - } - - auto ctx = _context; + auto ctx = (duk_context*)_context; ScConsole::Register(ctx); ScContext::Register(ctx); ScDisposable::Register(ctx); diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index a3f2cc0386..8d2f7b36a5 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -58,13 +58,30 @@ namespace OpenRCT2::Scripting std::shared_ptr GetCurrentPlugin() { return _plugin; } }; + class DukContext + { + private: + duk_context * _context{}; + + public: + DukContext(); + DukContext(DukContext&) = delete; + DukContext(DukContext&& src) + : _context(std::move(src._context)) + { + } + ~DukContext(); + + operator duk_context*() { return _context; } + }; + class ScriptEngine { private: InteractiveConsole& _console; IPlatformEnvironment& _env; + DukContext _context; bool _initialised{}; - duk_context * _context{}; std::queue, std::string>> _evalQueue; std::vector> _plugins; uint32 _lastHotReloadCheckTick{}; @@ -74,7 +91,6 @@ namespace OpenRCT2::Scripting public: ScriptEngine(InteractiveConsole& console, IPlatformEnvironment& env); ScriptEngine(ScriptEngine&) = delete; - ~ScriptEngine(); HookEngine& GetHookEngine() { return _hookEngine; }