Lua address several memory leaks - when a script stops, take any registered functions and spawn new threads for them to execute, and regularly dispose them. Also, the main lua thread needs to have scheduled disposes run on it, even if there is no active scripts (it was being run as part of disposing individual scripts, needs refactoring). All of this fixes #1920

This commit is contained in:
adelikat 2020-07-12 15:48:45 -05:00
parent 9278c526d0
commit ed9b7b3eb1
5 changed files with 39 additions and 9 deletions

View File

@ -23,13 +23,7 @@ namespace BizHawk.Client.Common
// and we should refactor
if (luaFile == null)
{
var thread = new Lua();
// Current dir will have to do for now, but this will inevitably not be desired
// Users will expect it to be the same directly as the thread that spawned this callback
// But how do we know what that directory was?
LuaSandbox.CreateSandbox(thread, ".");
LuaFile = new LuaFile(".") { Thread = thread };
DetachFromScript();
}
else
{
@ -53,11 +47,22 @@ namespace BizHawk.Client.Common
MemCallback = (address, value, flags) => Callback();
}
public void DetachFromScript()
{
var thread = new Lua();
// Current dir will have to do for now, but this will inevitably not be desired
// Users will expect it to be the same directly as the thread that spawned this callback
// But how do we know what that directory was?
LuaSandbox.CreateSandbox(thread, ".");
LuaFile = new LuaFile(".") { Thread = thread };
}
public Guid Guid { get; }
public string Name { get; }
public LuaFile LuaFile { get; }
public LuaFile LuaFile { get; private set; }
public string Event { get; }

View File

@ -635,6 +635,7 @@ namespace BizHawk.Client.EmuHawk
if (!prohibit)
{
var result = LuaImp.ResumeScript(lf);
DetachRegisteredFunctions(lf);
if (result.Terminated)
{
LuaImp.CallExitEvent(lf);
@ -647,6 +648,7 @@ namespace BizHawk.Client.EmuHawk
}, () =>
{
lf.Stop();
DetachRegisteredFunctions(lf);
LuaListView.Refresh();
});
}
@ -656,9 +658,24 @@ namespace BizHawk.Client.EmuHawk
}
}
LuaImp.RunScheduledDisposes();
foreach (var nlf in LuaImp.RegisteredFunctions)
{
nlf.LuaFile.Thread.RunScheduledDisposes();
}
_messageCount = 0;
}
private void DetachRegisteredFunctions(LuaFile lf)
{
foreach (var nlf in LuaImp.RegisteredFunctions
.Where(f => f.LuaFile == lf))
{
nlf.DetachFromScript();
}
}
private FileInfo GetSaveFileFromUser()
{
var sfd = new SaveFileDialog();

View File

@ -34,5 +34,7 @@ namespace BizHawk.Client.EmuHawk
public abstract void SpawnAndSetFileThread(string pathToLoad, LuaFile lf);
public abstract void StartLuaDrawing();
public abstract void WindowClosed(IntPtr handle);
public abstract void RunScheduledDisposes();
}
}

View File

@ -54,5 +54,9 @@ namespace BizHawk.Client.EmuHawk
public override void WindowClosed(IntPtr handle)
{
}
public override void RunScheduledDisposes()
{
}
}
}

View File

@ -192,6 +192,8 @@ namespace BizHawk.Client.EmuHawk
_lua.Pop();
}
public override void RunScheduledDisposes() => _lua.RunScheduledDisposes();
public override ResumeResult ResumeScript(LuaFile lf)
{
_currThread = lf.Thread;
@ -202,7 +204,7 @@ namespace BizHawk.Client.EmuHawk
var execResult = _currThread.Resume(0);
_lua.RunScheduledDisposes();
_lua.RunScheduledDisposes(); // TODO: I don't think this is needed anymore, we run this regularly anyway
// not sure how this is going to work out, so do this too
_currThread.RunScheduledDisposes();