Skip to content

Commit a4ae2bf

Browse files
committed
Apply misc fixes to LuaRPC:
- prevent premature helper gc - replace some MYASSERT statements with standard Lua functions for arg checking
1 parent a148d39 commit a4ae2bf

File tree

3 files changed

+58
-23
lines changed

3 files changed

+58
-23
lines changed

inc/luarpc_rpc.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ struct _Handle
103103
typedef struct _Helper Helper;
104104
struct _Helper {
105105
Handle *handle; // pointer to handle object
106-
Helper *parent; // parent helper
107-
u8 nparents; // number of parents
106+
Helper *parent; // parent helper
107+
int pref; // Parent reference idx in registry
108+
u8 nparents; // number of parents
108109
char funcname[NUM_FUNCNAME_CHARS]; // name of the function
109110
};
110111

src/modules/luarpc.c

+38-21
Original file line numberDiff line numberDiff line change
@@ -762,10 +762,13 @@ static Helper *helper_create( lua_State *L, Handle *handle, const char *funcname
762762
Helper *h = ( Helper * )lua_newuserdata( L, sizeof( Helper ) );
763763
luaL_getmetatable( L, "rpc.helper" );
764764
lua_setmetatable( L, -2 );
765+
766+
lua_pushvalue( L, 1 ); // push parent handle
767+
h->pref = luaL_ref( L, LUA_REGISTRYINDEX ); // put ref into struct
765768
h->handle = handle;
766769
h->parent = NULL;
767770
h->nparents = 0;
768-
strncpy ( h->funcname, funcname, NUM_FUNCNAME_CHARS );
771+
strncpy( h->funcname, funcname, NUM_FUNCNAME_CHARS );
769772
return h;
770773
}
771774

@@ -775,7 +778,7 @@ static int handle_index (lua_State *L)
775778
{
776779
const char *s;
777780

778-
MYASSERT( lua_gettop( L ) == 2 );
781+
check_num_args( L, 2 );
779782
MYASSERT( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.handle" ) );
780783

781784
if( lua_type( L, 2 ) != LUA_TSTRING )
@@ -797,7 +800,7 @@ static int handle_newindex( lua_State *L )
797800
{
798801
const char *s;
799802

800-
MYASSERT( lua_gettop( L ) == 3 );
803+
check_num_args( L, 3 );
801804
MYASSERT( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.handle" ) );
802805

803806
if( lua_type( L, 2 ) != LUA_TSTRING )
@@ -928,11 +931,10 @@ static int helper_call (lua_State *L)
928931
int freturn = 0;
929932
Helper *h;
930933
Transport *tpt;
931-
MYASSERT( lua_gettop( L ) >= 1 );
932-
MYASSERT( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.helper" ) );
933-
934-
// get helper object and its transport
935-
h = ( Helper * )lua_touserdata( L, 1 );
934+
935+
h = ( Helper * )luaL_checkudata(L, 1, "rpc.helper");
936+
luaL_argcheck(L, h, 1, "helper expected");
937+
936938
tpt = &h->handle->tpt;
937939

938940
// capture special calls, otherwise execute normal remote call
@@ -1001,26 +1003,25 @@ static int helper_call (lua_State *L)
10011003
return freturn;
10021004
}
10031005

1004-
1005-
1006-
1006+
// __newindex even on helper
10071007
static int helper_newindex( lua_State *L )
10081008
{
10091009
struct exception e;
10101010
int freturn = 0;
10111011
int ret_code;
10121012
Helper *h;
10131013
Transport *tpt;
1014-
MYASSERT( lua_isuserdata( L, -3 ) && ismetatable_type( L, -3, "rpc.helper" ) );
1015-
MYASSERT( lua_isstring( L, -2 ) );
1016-
1017-
// get helper object and its transport
1018-
h = ( Helper * )lua_touserdata( L, -3 );
1014+
1015+
h = ( Helper * )luaL_checkudata(L, -3, "rpc.helper");
1016+
luaL_argcheck(L, h, -3, "helper expected");
1017+
1018+
luaL_checktype(L, -2, LUA_TSTRING );
1019+
10191020
tpt = &h->handle->tpt;
10201021

10211022
Try
10221023
{
1023-
// write function name
1024+
// index destination on remote side
10241025
helper_wait_ready( tpt, RPC_CMD_NEWINDEX );
10251026
helper_remote_index( h );
10261027

@@ -1055,19 +1056,22 @@ static Helper *helper_append( lua_State *L, Helper *helper, const char *funcname
10551056
Helper *h = ( Helper * )lua_newuserdata( L, sizeof( Helper ) );
10561057
luaL_getmetatable( L, "rpc.helper" );
10571058
lua_setmetatable( L, -2 );
1059+
1060+
lua_pushvalue( L, 1 ); // push parent
1061+
h->pref = luaL_ref( L, LUA_REGISTRYINDEX ); // put ref into struct
10581062
h->handle = helper->handle;
10591063
h->parent = helper;
10601064
h->nparents = helper->nparents + 1;
10611065
strncpy ( h->funcname, funcname, NUM_FUNCNAME_CHARS );
10621066
return h;
10631067
}
10641068

1065-
// indexing a handle returns a helper
1069+
// indexing a helper returns a helper
10661070
static int helper_index( lua_State *L )
10671071
{
10681072
const char *s;
10691073

1070-
MYASSERT( lua_gettop( L ) == 2 );
1074+
check_num_args( L, 2 );
10711075
MYASSERT( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.helper" ) );
10721076

10731077
if( lua_type( L, 2 ) != LUA_TSTRING )
@@ -1081,6 +1085,17 @@ static int helper_index( lua_State *L )
10811085
return 1;
10821086
}
10831087

1088+
static int helper_close (lua_State *L)
1089+
{
1090+
Helper *h = ( Helper * )luaL_checkudata(L, 1, "rpc.helper");
1091+
luaL_argcheck(L, h, 1, "helper expected");
1092+
1093+
luaL_unref(L, LUA_REGISTRYINDEX, h->pref);
1094+
h->pref = LUA_REFNIL;
1095+
return 0;
1096+
}
1097+
1098+
10841099
// **************************************************************************
10851100
// server side handle userdata objects.
10861101

@@ -1543,8 +1558,8 @@ static int rpc_dispatch( lua_State *L )
15431558
ServerHandle *handle;
15441559
check_num_args( L, 1 );
15451560

1546-
if ( ! ( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.server_handle" ) ) )
1547-
return luaL_error( L, "arg must be server handle" );
1561+
handle = ( ServerHandle * )luaL_checkudata(L, 1, "rpc.server_handle");
1562+
luaL_argcheck(L, handle, 1, "server handle expected");
15481563

15491564
handle = ( ServerHandle * )lua_touserdata( L, 1 );
15501565

@@ -1625,6 +1640,7 @@ const LUA_REG_TYPE rpc_helper[] =
16251640
{ LSTRKEY( "__call" ), LFUNCVAL( helper_call ) },
16261641
{ LSTRKEY( "__index" ), LFUNCVAL( helper_index ) },
16271642
{ LSTRKEY( "__newindex" ), LFUNCVAL( helper_newindex ) },
1643+
{ LSTRKEY( "__gc" ), LFUNCVAL( helper_close ) },
16281644
{ LNILKEY, LNILVAL }
16291645
};
16301646

@@ -1686,6 +1702,7 @@ static const luaL_reg rpc_helper[] =
16861702
{ "__call", helper_call },
16871703
{ "__index", helper_index },
16881704
{ "__newindex", helper_newindex },
1705+
{ "__gc", helper_close },
16891706
{ NULL, NULL }
16901707
};
16911708

test/test-rpc.lua

+17
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ assert(slave.test:get(), "couldn't get remote table")
3737
-- check that we can get entry on remote table
3838
assert(test_local.sval == slave.test:get().sval, "table field not equivalent")
3939

40+
-- ensure that we're not loosing critical objects in GC
41+
tval = 5
42+
y={}
43+
y.z={}
44+
y.z.x = tval
45+
slave.y=y
46+
47+
a={}
48+
for i=1,2 do
49+
a[i]=slave.y.z
50+
collectgarbage("collect")
51+
end
52+
for idx,val in ipairs(a) do
53+
assert(val:get().x == tval, "missing parent helper")
54+
assert(val.x:get() == tval, "missing parent helper")
55+
end
56+
4057
print("Memory Used: " .. slave.collectgarbage("count") .. " kB")
4158

4259
-- adc = slave.adc

0 commit comments

Comments
 (0)