[vlc-commits] Lua: remap file descriptors in Lua and GC at exit (fixes #8898)
Rémi Denis-Courmont
git at videolan.org
Mon Sep 30 18:20:53 CEST 2013
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Sep 30 19:17:55 2013 +0300| [f06dd9a2637591b1955e6a3519071692c5f8fc00] | committer: Rémi Denis-Courmont
Lua: remap file descriptors in Lua and GC at exit (fixes #8898)
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f06dd9a2637591b1955e6a3519071692c5f8fc00
---
modules/lua/intf.c | 11 ++--
modules/lua/libs/net.c | 148 ++++++++++++++++++++++++++++++++++++++++++++----
modules/lua/vlc.h | 4 ++
3 files changed, 148 insertions(+), 15 deletions(-)
diff --git a/modules/lua/intf.c b/modules/lua/intf.c
index d8eab71..a865972 100644
--- a/modules/lua/intf.c
+++ b/modules/lua/intf.c
@@ -199,7 +199,6 @@ static const luaL_Reg p_reg[] = { { NULL, NULL } };
static int Start_LuaIntf( vlc_object_t *p_this, const char *name )
{
intf_thread_t *p_intf = (intf_thread_t*)p_this;
- intf_sys_t *p_sys;
lua_State *L;
config_ChainParse( p_intf, "lua-", ppsz_intf_options, p_intf->p_cfg );
@@ -215,14 +214,17 @@ static int Start_LuaIntf( vlc_object_t *p_this, const char *name )
/* Cleaned up by vlc_object_release() */
p_intf->psz_header = strdup( name );
- p_intf->p_sys = (intf_sys_t*)malloc( sizeof(intf_sys_t) );
- if( !p_intf->p_sys )
+ intf_sys_t *p_sys = malloc( sizeof(*p_sys) );
+ if( unlikely(p_sys == NULL) )
{
free( p_intf->psz_header );
p_intf->psz_header = NULL;
return VLC_ENOMEM;
}
- p_sys = p_intf->p_sys;
+ p_intf->p_sys = p_sys;
+
+ vlclua_fd_init( p_sys );
+
p_sys->psz_filename = vlclua_find_file( "intf", name );
if( !p_sys->psz_filename )
{
@@ -399,6 +401,7 @@ void Close_LuaIntf( vlc_object_t *p_this )
lua_close( p_sys->L );
close( p_sys->fd[0] );
+ vlclua_fd_destroy( p_sys );
free( p_sys->psz_filename );
free( p_sys );
}
diff --git a/modules/lua/libs/net.c b/modules/lua/libs/net.c
index dd0719c..d1c5b5f 100644
--- a/modules/lua/libs/net.c
+++ b/modules/lua/libs/net.c
@@ -28,6 +28,7 @@
# include "config.h"
#endif
+#include <assert.h>
#include <errno.h>
#ifdef _WIN32
#include <io.h>
@@ -46,6 +47,114 @@
#include "../vlc.h"
#include "../libs.h"
+void vlclua_fd_init( intf_sys_t *sys )
+{
+ for( unsigned i = 0; i < (sizeof(sys->fds)/sizeof(sys->fds[0])); i++ )
+ sys->fds[i] = -1;
+}
+
+/** Releases all (leaked) VLC Lua file descriptors. */
+void vlclua_fd_destroy( intf_sys_t *sys )
+{
+ for( unsigned i = 0; i < (sizeof(sys->fds)/sizeof(sys->fds[0])); i++ )
+ if( sys->fds[i] != -1 )
+ net_Close( sys->fds[i] );
+}
+
+
+/** Maps an OS file descriptor to a VLC Lua file descriptor */
+static int vlclua_fd_map( lua_State *L, int fd )
+{
+ intf_thread_t *intf = (intf_thread_t *)vlclua_get_this( L );
+ intf_sys_t *sys = intf->p_sys;
+
+ if( (unsigned)fd < 3u )
+ return -1;
+
+#ifndef NDEBUG
+ for( unsigned i = 0; i < (sizeof(sys->fds)/sizeof(sys->fds[0])); i++ )
+ assert( sys->fds[i] != fd );
+#endif
+ for( unsigned i = 0; i < (sizeof(sys->fds)/sizeof(sys->fds[0])); i++ )
+ if( sys->fds[i] == -1 )
+ {
+ sys->fds[i] = fd;
+ return 3 + i;
+ }
+
+ return -1;
+}
+
+static int vlclua_fd_map_safe( lua_State *L, int fd )
+{
+ int luafd = vlclua_fd_map( L, fd );
+ if( luafd == -1 )
+ net_Close( fd );
+ return luafd;
+}
+
+/** Gets the OS file descriptor mapped to a VLC Lua file descriptor */
+static int vlclua_fd_get( lua_State *L, unsigned idx )
+{
+ intf_thread_t *intf = (intf_thread_t *)vlclua_get_this( L );
+ intf_sys_t *sys = intf->p_sys;
+
+ if( idx < 3u )
+ return idx;
+ idx -= 3;
+ if( sizeof(sys->fds[0]) * idx < sizeof(sys->fds) )
+ return sys->fds[idx];
+ return -1;
+}
+
+/** Gets the VLC Lua file descriptor mapped from an OS file descriptor */
+static int vlclua_fd_get_lua( lua_State *L, int fd )
+{
+ intf_thread_t *intf = (intf_thread_t *)vlclua_get_this( L );
+ intf_sys_t *sys = intf->p_sys;
+
+ if( (unsigned)fd < 3u )
+ return fd;
+ for( unsigned i = 0; i < (sizeof(sys->fds)/sizeof(sys->fds[0])); i++ )
+ if( sys->fds[i] == fd )
+ return 3 + i;
+ return -1;
+}
+
+/** Unmaps an OS file descriptor from VLC Lua */
+static void vlclua_fd_unmap( lua_State *L, unsigned idx )
+{
+ intf_thread_t *intf = (intf_thread_t *)vlclua_get_this( L );
+ intf_sys_t *sys = intf->p_sys;
+ int fd = -1;
+
+ if( idx < 3u )
+ return; /* Never close stdin/stdout/stderr. */
+
+ idx -= 3;
+ if( idx < (sizeof(sys->fds)/sizeof(sys->fds[0])) )
+ {
+ fd = sys->fds[idx];
+ sys->fds[idx] = -1;
+ }
+
+ if( fd == -1 )
+ return;
+#ifndef NDEBUG
+ for( unsigned i = 0; i < (sizeof(sys->fds)/sizeof(sys->fds[0])); i++ )
+ assert( sys->fds[i] != fd );
+#endif
+}
+
+static void vlclua_fd_unmap_safe( lua_State *L, unsigned idx )
+{
+ int fd = vlclua_fd_get( L, idx );
+
+ vlclua_fd_unmap( L, idx );
+ if( fd != -1 )
+ net_Close( fd );
+}
+
/*****************************************************************************
*
*****************************************************************************/
@@ -100,6 +209,16 @@ static int vlclua_net_listen_tcp( lua_State *L )
if( pi_fd == NULL )
return luaL_error( L, "Cannot listen on %s:%d", psz_host, i_port );
+ for( unsigned i = 0; pi_fd[i] != -1; i++ )
+ if( vlclua_fd_map( L, pi_fd[i] ) == -1 )
+ {
+ while( i > 0 )
+ vlclua_fd_unmap( L, vlclua_fd_get_lua( L, pi_fd[--i] ) );
+
+ net_ListenClose( pi_fd );
+ return luaL_error( L, "Cannot listen on %s:%d", psz_host, i_port );
+ }
+
int **ppi_fd = lua_newuserdata( L, sizeof( int * ) );
*ppi_fd = pi_fd;
@@ -119,7 +238,12 @@ static int vlclua_net_listen_tcp( lua_State *L )
static int vlclua_net_listen_close( lua_State *L )
{
int **ppi_fd = (int**)luaL_checkudata( L, 1, "net_listen" );
- net_ListenClose( *ppi_fd );
+ int *pi_fd = *ppi_fd;
+
+ for( unsigned i = 0; pi_fd[i] != -1; i++ )
+ vlclua_fd_unmap( L, vlclua_fd_get_lua( L, pi_fd[i] ) );
+
+ net_ListenClose( pi_fd );
return 0;
}
@@ -130,7 +254,7 @@ static int vlclua_net_fds( lua_State *L )
int i_count = 0;
while( pi_fd[i_count] != -1 )
- lua_pushinteger( L, pi_fd[i_count++] );
+ lua_pushinteger( L, vlclua_fd_get_lua( L, pi_fd[i_count++] ) );
return i_count;
}
@@ -141,7 +265,7 @@ static int vlclua_net_accept( lua_State *L )
int **ppi_fd = (int**)luaL_checkudata( L, 1, "net_listen" );
int i_fd = net_Accept( p_this, *ppi_fd );
- lua_pushinteger( L, i_fd );
+ lua_pushinteger( L, vlclua_fd_map_safe( L, i_fd ) );
return 1;
}
@@ -154,14 +278,14 @@ static int vlclua_net_connect_tcp( lua_State *L )
const char *psz_host = luaL_checkstring( L, 1 );
int i_port = luaL_checkint( L, 2 );
int i_fd = net_Connect( p_this, psz_host, i_port, SOCK_STREAM, IPPROTO_TCP );
- lua_pushinteger( L, i_fd );
+ lua_pushinteger( L, vlclua_fd_map_safe( L, i_fd ) );
return 1;
}
static int vlclua_net_close( lua_State *L )
{
int i_fd = luaL_checkint( L, 1 );
- net_Close( i_fd );
+ vlclua_fd_unmap_safe( L, i_fd );
return 0;
}
@@ -171,7 +295,7 @@ static int vlclua_net_send( lua_State *L )
size_t i_len;
const char *psz_buffer = luaL_checklstring( L, 2, &i_len );
i_len = luaL_optint( L, 3, i_len );
- i_len = send( i_fd, psz_buffer, i_len, 0 );
+ i_len = send( vlclua_fd_get( L, i_fd ), psz_buffer, i_len, 0 );
lua_pushinteger( L, i_len );
return 1;
}
@@ -181,7 +305,7 @@ static int vlclua_net_recv( lua_State *L )
int i_fd = luaL_checkint( L, 1 );
size_t i_len = luaL_optint( L, 2, 1 );
char psz_buffer[i_len];
- ssize_t i_ret = recv( i_fd, psz_buffer, i_len, 0 );
+ ssize_t i_ret = recv( vlclua_fd_get( L, i_fd ), psz_buffer, i_len, 0 );
if( i_ret > 0 )
lua_pushlstring( L, psz_buffer, i_ret );
else
@@ -210,6 +334,7 @@ static int vlclua_net_poll( lua_State *L )
}
struct pollfd *p_fds = xmalloc( i_fds * sizeof( *p_fds ) );
+ int *luafds = xmalloc( i_fds * sizeof( *luafds ) );
lua_pushnil( L );
int i = 1;
@@ -217,7 +342,8 @@ static int vlclua_net_poll( lua_State *L )
p_fds[0].events = POLLIN;
while( lua_next( L, 1 ) )
{
- p_fds[i].fd = luaL_checkinteger( L, -2 );
+ luafds[i] = luaL_checkinteger( L, -2 );
+ p_fds[i].fd = vlclua_fd_get( L, luafds[i] );
p_fds[i].events = luaL_checkinteger( L, -1 );
lua_pop( L, 1 );
i++;
@@ -230,7 +356,7 @@ static int vlclua_net_poll( lua_State *L )
for( i = 1; i < i_fds; i++ )
{
- lua_pushinteger( L, p_fds[i].fd );
+ lua_pushinteger( L, luafds[i] );
lua_pushinteger( L, p_fds[i].revents );
lua_settable( L, 1 );
}
@@ -261,7 +387,7 @@ static int vlclua_fd_write( lua_State *L )
ssize_t i_ret;
const char *psz_buffer = luaL_checklstring( L, 2, &i_len );
i_len = luaL_optint( L, 3, i_len );
- i_ret = write( i_fd, psz_buffer, i_len );
+ i_ret = write( vlclua_fd_get( L, i_fd ), psz_buffer, i_len );
lua_pushinteger( L, i_ret );
return 1;
}
@@ -271,7 +397,7 @@ static int vlclua_fd_read( lua_State *L )
int i_fd = luaL_checkint( L, 1 );
size_t i_len = luaL_optint( L, 2, 1 );
char psz_buffer[i_len];
- ssize_t i_ret = read( i_fd, psz_buffer, i_len );
+ ssize_t i_ret = read( vlclua_fd_get( L, i_fd ), psz_buffer, i_len );
if( i_ret > 0 )
lua_pushlstring( L, psz_buffer, i_ret );
else
diff --git a/modules/lua/vlc.h b/modules/lua/vlc.h
index 9ea05cf..5c1940c 100644
--- a/modules/lua/vlc.h
+++ b/modules/lua/vlc.h
@@ -161,9 +161,13 @@ struct intf_sys_t
#ifndef _WIN32
int fd[2];
#endif
+ int fds[64];
vlc_thread_t thread;
};
+void vlclua_fd_init( struct intf_sys_t * );
+void vlclua_fd_destroy( struct intf_sys_t * );
+
#endif /* VLC_LUA_H */
More information about the vlc-commits
mailing list