Merge pull request #5370 from pavlos256/lua-dispose-crash

Possible fix for lua crash #5269
This commit is contained in:
Paul Chote
2014-05-20 12:38:40 +12:00
3 changed files with 56 additions and 23 deletions

View File

@@ -81,11 +81,12 @@ namespace OpenRA.Scripting
public ScriptGlobalAttribute(string name) { Name = name; }
}
public class ScriptContext
public class ScriptContext : IDisposable
{
public World World { get; private set; }
public WorldRenderer WorldRenderer { get; private set; }
bool disposed;
readonly MemoryConstrainedLuaRuntime runtime;
readonly LuaFunction tick;
@@ -188,26 +189,34 @@ namespace OpenRA.Scripting
public void Tick(Actor self)
{
if (error)
if (error || disposed)
return;
using (new PerfSample("tick_lua"))
tick.Call().Dispose();
}
public void Dispose()
protected void Dispose(bool disposing)
{
if (runtime == null)
if (disposed)
return;
if (disposing)
runtime.Dispose();
disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
runtime.Dispose();
}
~ScriptContext()
{
if (runtime != null)
Game.RunAfterTick(Dispose);
// Dispose unmanaged resources only
Dispose(false);
}
static Type[] ExtractRequiredTypes(Type t)

View File

@@ -15,12 +15,13 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
{
public class CallLuaFunc : Activity
public class CallLuaFunc : Activity, IDisposable
{
LuaFunction function;
public CallLuaFunc(LuaFunction func)
{
function = func.CopyReference() as LuaFunction;
function = (LuaFunction)func.CopyReference();
}
public override Activity Tick(Actor self)
@@ -38,20 +39,28 @@ namespace OpenRA.Mods.RA.Activities
base.Cancel(self);
}
public void Dispose()
protected void Dispose(bool disposing)
{
if (function == null)
return;
if (disposing)
{
function.Dispose();
function = null;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
function.Dispose();
function = null;
}
~CallLuaFunc()
{
if (function != null)
Game.RunAfterTick(Dispose);
// Dispose unmanaged resources only
Dispose(false);
}
}
}

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.RA.Scripting
[Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")]
public class ScriptTriggersInfo : TraitInfo<ScriptTriggers> { }
public class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction
public class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, IDisposable
{
public event Action<Actor> OnKilledInternal = _ => {};
@@ -101,21 +101,36 @@ namespace OpenRA.Mods.RA.Scripting
}
bool disposed;
protected void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
var toDispose = new [] { onIdle, onDamaged, onKilled, onProduction };
foreach (var f in toDispose.SelectMany(f => f))
f.First.Dispose();
foreach (var l in toDispose)
l.Clear();
}
disposed = true;
}
public void Dispose()
{
disposed = true;
var toDispose = new [] { onIdle, onDamaged, onKilled, onProduction };
foreach (var f in toDispose.SelectMany(f => f))
f.First.Dispose();
Dispose(true);
GC.SuppressFinalize(this);
}
~ScriptTriggers()
{
if (!disposed)
Game.RunAfterTick(Dispose);
// Dispose unmanaged resources only
Dispose(false);
}
}
}