AP_Scripting: fixed memory leak in sendfile()

this leaked the SocketAPM on each sendfile() call, we now rely on the
script calling close(). The net_webserver.lua is already using close()
correctly, this change just makes close able to find the socket
This commit is contained in:
Andrew Tridgell 2024-01-04 10:23:57 +11:00
parent 7292c89766
commit efac52136b
3 changed files with 29 additions and 52 deletions

View File

@ -328,7 +328,6 @@ void AP_Scripting::thread(void) {
_net_sockets[i] = nullptr; _net_sockets[i] = nullptr;
} }
} }
num_net_sockets = 0;
#endif // AP_NETWORKING_ENABLED #endif // AP_NETWORKING_ENABLED
// Clear blocked commands // Clear blocked commands

View File

@ -121,7 +121,6 @@ public:
#if AP_NETWORKING_ENABLED #if AP_NETWORKING_ENABLED
// SocketAPM storage // SocketAPM storage
uint8_t num_net_sockets;
SocketAPM *_net_sockets[SCRIPTING_MAX_NUM_NET_SOCKET]; SocketAPM *_net_sockets[SCRIPTING_MAX_NUM_NET_SOCKET];
#endif #endif

View File

@ -794,22 +794,20 @@ int lua_get_SocketAPM(lua_State *L) {
const uint8_t datagram = get_uint8_t(L, 1); const uint8_t datagram = get_uint8_t(L, 1);
auto *scripting = AP::scripting(); auto *scripting = AP::scripting();
if (scripting->num_net_sockets >= SCRIPTING_MAX_NUM_NET_SOCKET) {
return luaL_argerror(L, 1, "no sockets available");
}
auto *sock = new SocketAPM(datagram); auto *sock = new SocketAPM(datagram);
if (sock == nullptr) { if (sock == nullptr) {
return luaL_argerror(L, 1, "SocketAPM device nullptr"); return luaL_argerror(L, 1, "SocketAPM device nullptr");
} }
scripting->_net_sockets[scripting->num_net_sockets] = sock; for (uint8_t i=0; i<SCRIPTING_MAX_NUM_NET_SOCKET; i++) {
if (scripting->_net_sockets[i] == nullptr) {
scripting->_net_sockets[i] = sock;
new_SocketAPM(L);
*((SocketAPM**)luaL_checkudata(L, -1, "SocketAPM")) = scripting->_net_sockets[i];
return 1;
}
}
new_SocketAPM(L); return luaL_argerror(L, 1, "no sockets available");
*((SocketAPM**)luaL_checkudata(L, -1, "SocketAPM")) = scripting->_net_sockets[scripting->num_net_sockets];
scripting->num_net_sockets++;
return 1;
} }
/* /*
@ -822,17 +820,12 @@ int SocketAPM_close(lua_State *L) {
auto *scripting = AP::scripting(); auto *scripting = AP::scripting();
if (scripting->num_net_sockets == 0) {
return luaL_argerror(L, 1, "socket close error");
}
// clear allocated socket // clear allocated socket
for (uint8_t i=0; i<SCRIPTING_MAX_NUM_NET_SOCKET; i++) { for (uint8_t i=0; i<SCRIPTING_MAX_NUM_NET_SOCKET; i++) {
if (scripting->_net_sockets[i] == ud) { if (scripting->_net_sockets[i] == ud) {
ud->close(); ud->close();
delete ud; delete ud;
scripting->_net_sockets[i] = nullptr; scripting->_net_sockets[i] = nullptr;
scripting->num_net_sockets--;
break; break;
} }
} }
@ -848,28 +841,15 @@ int SocketAPM_sendfile(lua_State *L) {
SocketAPM *ud = *check_SocketAPM(L, 1); SocketAPM *ud = *check_SocketAPM(L, 1);
auto *scripting = AP::scripting();
if (scripting->num_net_sockets == 0) {
return luaL_argerror(L, 1, "sendfile error");
}
auto *p = (luaL_Stream *)luaL_checkudata(L, 2, LUA_FILEHANDLE); auto *p = (luaL_Stream *)luaL_checkudata(L, 2, LUA_FILEHANDLE);
int fd = p->f->fd; int fd = p->f->fd;
bool ret = false;
// find the socket bool ret = fd != -1 && AP::network().sendfile(ud, fd);
for (uint8_t i=0; i<SCRIPTING_MAX_NUM_NET_SOCKET; i++) { if (ret) {
if (scripting->_net_sockets[i] == ud) { // the fd is no longer valid. The lua script must
ret = AP::network().sendfile(ud, fd); // still call close() to release the memory from the
if (ret) { // socket
// remove from scripting, leave socket and fd open p->f->fd = -1;
p->f->fd = -1;
scripting->_net_sockets[i] = nullptr;
scripting->num_net_sockets--;
}
break;
}
} }
lua_pushboolean(L, ret); lua_pushboolean(L, ret);
@ -912,23 +892,22 @@ int SocketAPM_accept(lua_State *L) {
SocketAPM * ud = *check_SocketAPM(L, 1); SocketAPM * ud = *check_SocketAPM(L, 1);
auto *scripting = AP::scripting(); auto *scripting = AP::scripting();
if (scripting->num_net_sockets >= SCRIPTING_MAX_NUM_NET_SOCKET) {
return 0; // find an empty slot
for (uint8_t i=0; i<SCRIPTING_MAX_NUM_NET_SOCKET; i++) {
if (scripting->_net_sockets[i] == nullptr) {
scripting->_net_sockets[i] = ud->accept(0);
if (scripting->_net_sockets[i] == nullptr) {
return 0;
}
new_SocketAPM(L);
*((SocketAPM**)luaL_checkudata(L, -1, "SocketAPM")) = scripting->_net_sockets[i];
return 1;
}
} }
auto *sock = ud->accept(0); // out of socket slots, return nil, caller can retry
if (sock == nullptr) { return 0;
return 0;
}
scripting->_net_sockets[scripting->num_net_sockets] = sock;
new_SocketAPM(L);
*((SocketAPM**)luaL_checkudata(L, -1, "SocketAPM")) = scripting->_net_sockets[scripting->num_net_sockets];
scripting->num_net_sockets++;
return 1;
} }
#endif // AP_NETWORKING_ENABLED #endif // AP_NETWORKING_ENABLED