Fix tasks crashing memory and stuff

This commit is contained in:
Alessandro Proto 2023-03-07 22:09:05 +01:00
parent d137c46ed9
commit 9aadc35329
5 changed files with 74 additions and 68 deletions

View file

@ -24,6 +24,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Capy64.Runtime.Libraries;
@ -527,7 +528,12 @@ public class GPU : IComponent
Height = texture.Height,
Width = texture.Width,
};
task.Fulfill(buffer);
task.Fulfill(lk =>
{
ObjectManager.PushObject(lk, buffer);
lk.SetMetaTable(GPUBufferMeta.ObjectType);
});
texture.Dispose();
});

View file

@ -25,6 +25,7 @@ using System.Net.Http;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Capy64.Runtime.Libraries;
#nullable enable
@ -198,19 +199,15 @@ public class HTTP : IComponent
var requestId = _requestId++;
var luaTask = TaskMeta.Push(L, "HTTPRequest");
var reqTask = _httpClient.SendAsync(request);
reqTask.ContinueWith(async (task) =>
{
if (task.IsFaulted || task.IsCanceled)
{
_game.LuaRuntime.QueueEvent("http_failure", LK =>
{
LK.PushInteger(requestId);
LK.PushString(task.Exception?.Message);
return 2;
});
luaTask.Reject(task.Exception?.Message);
return;
}
@ -218,23 +215,15 @@ public class HTTP : IComponent
var stream = await response.Content.ReadAsStreamAsync();
_game.LuaRuntime.QueueEvent("http_response", LK =>
luaTask.Fulfill(LK =>
{
// arg 1, request id
LK.PushInteger(requestId);
// arg 2, response data
ObjectManager.PushObject(L, stream);
//L.PushObject(stream);
L.SetMetaTable(FileHandle.ObjectType);
/*if ((bool)options["binary"])
BinaryReadHandle.Push(LK, new(stream));
else
ReadHandle.Push(LK, new(stream));*/
// arg 3, response info
LK.NewTable();
LK.PushString("content");
ObjectManager.PushObject(LK, stream);
LK.SetMetaTable(FileHandle.ObjectType);
LK.SetTable(-3);
LK.PushString("success");
LK.PushBoolean(response.IsSuccessStatusCode);
LK.SetTable(-3);
@ -258,15 +247,9 @@ public class HTTP : IComponent
}
LK.SetTable(-3);
return 3;
});
});
L.PushInteger(requestId);
return 1;
}

View file

@ -26,7 +26,7 @@ namespace Capy64.Runtime;
public class LuaState : IDisposable
{
public Lua Thread;
private readonly Lua _parent;
public readonly Lua Parent;
private readonly ConcurrentQueue<LuaEvent> _queue = new();
@ -36,25 +36,21 @@ public class LuaState : IDisposable
public LuaState()
{
_parent = new Lua(false)
Parent = new Lua(false)
{
Encoding = Encoding.UTF8,
};
Sandbox.OpenLibraries(_parent);
Sandbox.Patch(_parent);
Sandbox.OpenLibraries(Parent);
Sandbox.Patch(Parent);
Thread = _parent.NewThread();
Thread = Parent.NewThread();
Thread.SetHook(LH_YieldTimeout, LuaHookMask.Count, 7000);
yieldTimeoutTimer.Elapsed += (sender, ev) =>
{
yieldTimedOut = true;
};
InitPlugins();
Thread.SetTop(0);
}
private static void LH_YieldTimeout(IntPtr state, IntPtr ar)
@ -68,6 +64,13 @@ public class LuaState : IDisposable
}
}
public void Init()
{
InitPlugins();
Thread.SetTop(0);
}
private void InitPlugins()
{
var allPlugins = new List<IComponent>(Capy64.Instance.NativePlugins);
@ -192,6 +195,6 @@ public class LuaState : IDisposable
GC.SuppressFinalize(this);
_queue.Clear();
Thread.Close();
_parent.Close();
Parent.Close();
}
}

View file

@ -44,19 +44,23 @@ public class TaskMeta : IComponent
}
public class RuntimeTask
{
public RuntimeTask(string typeName)
public RuntimeTask(string name)
{
TypeName = typeName;
Name = name;
}
public RuntimeTask() { }
public Guid Guid { get; set; } = Guid.NewGuid();
public string TypeName { get; set; }
public string Name { get; set; } = "object";
public TaskStatus Status { get; set; } = TaskStatus.Running;
public object Result { get; private set; }
public string Error { get; private set; }
public int DataIndex { get; private set; } = 0;
public void Fulfill<T>(T obj)
{
Status = TaskStatus.Succeeded;
/*Status = TaskStatus.Succeeded;
Result = obj;
@ -65,32 +69,30 @@ public class TaskMeta : IComponent
LK.PushString(Guid.ToString());
ObjectManager.PushObject(LK, obj);
LK.SetMetaTable(TypeName);
LK.SetMetaTable(Name);
LK.PushNil();
return 3;
});
});*/
}
public void Fulfill(Action<Lua> lk)
{
Status = TaskStatus.Succeeded;
var container = tasks.NewThread();
lk(container);
container.XMove(tasks, 1);
tasks.Replace(-2);
DataIndex = tasks.GetTop();
_game.LuaRuntime.QueueEvent("task_finish", LK =>
{
LK.PushString(Guid.ToString());
// Create Lua thread to store Lua native result data
Result = LK.NewThread();
var thread = (Lua)Result;
LK.Pop(1);
lk(thread);
// Push copy of value on top and move it to LK
thread.PushCopy(-1);
thread.XMove(LK, 1);
tasks.PushCopy(DataIndex);
tasks.XMove(LK, 1);
LK.PushNil();
@ -176,8 +178,11 @@ public class TaskMeta : IComponent
new(),
};
private static Lua tasks;
public void LuaInit(Lua L)
{
tasks = _game.LuaRuntime.Parent.NewThread();
CreateMeta(L);
}
@ -211,7 +216,7 @@ public class TaskMeta : IComponent
var obj = ObjectManager.CheckObject<RuntimeTask>(L, 1, ObjectType, gc);
if (obj is null)
{
L.Error("attempt to use a closed file");
L.Error("attempt to use a closed task");
return null;
}
return obj;
@ -265,7 +270,7 @@ public class TaskMeta : IComponent
var task = CheckTask(L, false);
L.PushString(task.TypeName);
L.PushString(task.Name);
return 1;
}
@ -289,17 +294,9 @@ public class TaskMeta : IComponent
if (task.Status == TaskStatus.Succeeded)
{
if (task.Result is Lua thread)
{
// Push copy of value on top and move it to LK
thread.PushCopy(-1);
thread.XMove(L, 1);
}
else
{
ObjectManager.PushObject(L, task.Result);
L.SetMetaTable(task.TypeName);
}
// Push copy of value on top and move it to L
tasks.PushCopy(task.DataIndex);
tasks.XMove(L, 1);
}
else
{
@ -329,6 +326,21 @@ public class TaskMeta : IComponent
private static int LM_GC(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var task = ToTask(L, true);
if (task is null)
return 0;
// todo: add cleanup to remove nil values at top of stack
if (tasks.GetTop() == task.DataIndex)
tasks.SetTop(task.DataIndex - 1);
else
{
tasks.PushNil();
tasks.Replace(task.DataIndex);
}
return 0;
}
@ -336,7 +348,7 @@ public class TaskMeta : IComponent
{
var L = Lua.FromIntPtr(state);
var task = ToTask(L);
L.PushString("Task<{0}>: {1} ({2})", task?.TypeName, task?.Guid, task?.Status);
L.PushString("Task<{0}>: {1} ({2})", task?.Name, task?.Guid, task?.Status);
return 1;
}

View file

@ -100,6 +100,7 @@ internal class RuntimeManager : IComponent
luaState = new LuaState();
_game.LuaRuntime = luaState;
luaState.Init();
emitter = new(_game.EventEmitter, luaState);
@ -136,6 +137,7 @@ internal class RuntimeManager : IComponent
luaState = new LuaState();
_game.LuaRuntime = luaState;
luaState.Init();
emitter = new(_game.EventEmitter, luaState);