fix "cannot resume dead coroutine" for servers

This commit is contained in:
MihailRis 2025-07-26 17:08:45 +03:00
parent 8489c36df7
commit 1bd3463488
7 changed files with 78 additions and 24 deletions

View File

@ -60,8 +60,37 @@ local ServerSocket = {__index={
get_port=function(self) return network.__get_serverport(self.id) end,
}}
network.tcp_open = function(port, handler)
return setmetatable({id=network.__open(port, function(id)
local _tcp_server_callbacks = {}
network.tcp_open = function (port, handler)
local socket = setmetatable({id=network.__open(port)}, ServerSocket)
_tcp_server_callbacks[socket.id] = function(id)
handler(setmetatable({id=id}, Socket))
end)}, ServerSocket)
end
return socket
end
network.__pull_events = function()
local cleaned = false
local connections = network.__pull_connections()
for i, pair in ipairs(connections) do
local sid, cid = unpack(pair)
local callback = _tcp_server_callbacks[sid]
if callback then
callback(cid)
end
-- remove dead servers
if not cleaned then
for sid, callback in pairs(_tcp_server_callbacks) do
if not network.__is_serveropen(sid) then
_tcp_server_callbacks[sid] = nil
end
end
cleaned = true
end
end
end

View File

@ -34,7 +34,10 @@ local function complete_app_lib(app)
app.reconfig_packs = core.reconfig_packs
app.get_setting = core.get_setting
app.set_setting = core.set_setting
app.tick = coroutine.yield
app.tick = function()
coroutine.yield()
network.__pull_events()
end
app.get_version = core.get_version
app.get_setting_info = core.get_setting_info
app.load_content = function()

View File

@ -44,11 +44,11 @@ public:
};
struct CoreParameters {
bool headless = false;
bool headless = true;
bool testMode = false;
std::filesystem::path resFolder = "res";
std::filesystem::path userFolder = ".";
std::filesystem::path scriptFile;
std::filesystem::path scriptFile = "res/content/remp/remp_server.lua";
std::filesystem::path projectFolder;
};

View File

@ -182,14 +182,17 @@ static int l_available(lua::State* L, network::Network& network) {
return 0;
}
struct ConnectionEvent {
u64id_t server;
u64id_t client;
};
static std::vector<ConnectionEvent> clients_queue {};
static int l_open(lua::State* L, network::Network& network) {
int port = lua::tointeger(L, 1);
lua::pushvalue(L, 2);
auto callback = lua::create_lambda_nothrow(L);
u64id_t id = network.openServer(port, [callback](u64id_t id) {
engine->postRunnable([=]() {
callback({id});
});
u64id_t id = network.openServer(port, [](u64id_t sid, u64id_t id) {
clients_queue.push_back({sid, id});
});
return lua::pushinteger(L, id);
}
@ -250,6 +253,23 @@ static int l_get_total_download(lua::State* L, network::Network& network) {
return lua::pushinteger(L, network.getTotalDownload());
}
static int l_pull_connections(lua::State* L, network::Network& network) {
lua::createtable(L, clients_queue.size(), 0);
for (size_t i = 0; i < clients_queue.size(); i++) {
lua::createtable(L, 2, 0);
lua::pushinteger(L, clients_queue[i].server);
lua::rawseti(L, 1);
lua::pushinteger(L, clients_queue[i].client);
lua::rawseti(L, 2);
lua::rawseti(L, i + 1);
}
clients_queue.clear();
return 1;
}
template <int(*func)(lua::State*, network::Network&)>
int wrap(lua_State* L) {
int result = 0;
@ -267,13 +287,13 @@ int wrap(lua_State* L) {
return result;
}
const luaL_Reg networklib[] = {
{"get", wrap<l_get>},
{"get_binary", wrap<l_get_binary>},
{"post", wrap<l_post>},
{"get_total_upload", wrap<l_get_total_upload>},
{"get_total_download", wrap<l_get_total_download>},
{"__pull_connections", wrap<l_pull_connections>},
{"__open", wrap<l_open>},
{"__closeserver", wrap<l_closeserver>},
{"__connect", wrap<l_connect>},

View File

@ -90,7 +90,7 @@ public:
}
void update() override {
if (id == 0) {
if (!alive || id == 0) {
return;
}
if (lua::requireglobal(L, "__vc_resume_coroutine")) {

View File

@ -477,6 +477,7 @@ public:
};
class SocketTcpSServer : public TcpServer {
u64id_t id;
Network* network;
SOCKET descriptor;
std::vector<u64id_t> clients;
@ -485,14 +486,14 @@ class SocketTcpSServer : public TcpServer {
std::unique_ptr<std::thread> thread = nullptr;
int port;
public:
SocketTcpSServer(Network* network, SOCKET descriptor, int port)
: network(network), descriptor(descriptor), port(port) {}
SocketTcpSServer(u64id_t id, Network* network, SOCKET descriptor, int port)
: id(id), network(network), descriptor(descriptor), port(port) {}
~SocketTcpSServer() {
closeSocket();
}
void startListen(consumer<u64id_t> handler) override {
void startListen(ConnectCallback handler) override {
thread = std::make_unique<std::thread>([this, handler]() {
while (open) {
logger.info() << "listening for connections";
@ -518,7 +519,7 @@ public:
std::lock_guard lock(clientsMutex);
clients.push_back(id);
}
handler(id);
handler(this->id, id);
}
});
}
@ -558,7 +559,7 @@ public:
}
static std::shared_ptr<SocketTcpSServer> openServer(
Network* network, int port, consumer<u64id_t> handler
u64id_t id, Network* network, int port, ConnectCallback handler
) {
SOCKET descriptor = socket(
AF_INET, SOCK_STREAM, 0
@ -585,7 +586,7 @@ public:
}
logger.info() << "opened server at port " << port;
auto server =
std::make_shared<SocketTcpSServer>(network, descriptor, port);
std::make_shared<SocketTcpSServer>(id, network, descriptor, port);
server->startListen(std::move(handler));
return server;
}
@ -645,9 +646,9 @@ u64id_t Network::connect(const std::string& address, int port, consumer<u64id_t>
return id;
}
u64id_t Network::openServer(int port, consumer<u64id_t> handler) {
u64id_t Network::openServer(int port, ConnectCallback handler) {
u64id_t id = nextServer++;
auto server = SocketTcpSServer::openServer(this, port, handler);
auto server = SocketTcpSServer::openServer(id, this, port, handler);
servers[id] = std::move(server);
return id;
}

View File

@ -12,6 +12,7 @@
namespace network {
using OnResponse = std::function<void(std::vector<char>)>;
using OnReject = std::function<void(int)>;
using ConnectCallback = std::function<void(u64id_t, u64id_t)>;
class Requests {
public:
@ -64,7 +65,7 @@ namespace network {
class TcpServer {
public:
virtual ~TcpServer() {}
virtual void startListen(consumer<u64id_t> handler) = 0;
virtual void startListen(ConnectCallback handler) = 0;
virtual void close() = 0;
virtual bool isOpen() = 0;
virtual int getPort() const = 0;
@ -106,7 +107,7 @@ namespace network {
u64id_t connect(const std::string& address, int port, consumer<u64id_t> callback);
u64id_t openServer(int port, consumer<u64id_t> handler);
u64id_t openServer(int port, ConnectCallback handler);
u64id_t addConnection(const std::shared_ptr<Connection>& connection);