From b335cbcc9f07dc71999b885ffa2962c0ec00f5eb Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Mon, 6 Jan 2014 10:40:14 +0100 Subject: fix on_state_create circular logic issue * if config.on_state_create() is a C function, call it by direct C closure reconstruction in newly created states * bumped version to 3.7.6 --- CHANGES | 4 ++++ docs/index.html | 10 +++++++--- src/lanes.c | 25 +++++++++++++------------ src/lanes.lua | 2 +- src/threading.c | 4 ++-- src/tools.c | 56 +++++++++++++++++++++++++++++++++++++++++++------------- src/tools.h | 3 ++- 7 files changed, 72 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index c196455..7fac3e3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ CHANGES: +CHANGE 88: BGe 06-Jan-14 + * version 3.7.6 + * if config.on_state_create() is a C function, call it by direct C closure reconstruction in newly created states + CHANGE 87: BGe 20-Dec-13 * version 3.7.5 * fixed a crash that can occur at shutdown when an object stored inside a keeper state performs a linda operation on a linda making use of another keeper diff --git a/docs/index.html b/docs/index.html index f25463d..931a961 100644 --- a/docs/index.html +++ b/docs/index.html @@ -64,13 +64,13 @@


- Copyright © 2007-13 Asko Kauppi, Benoit Germain. All rights reserved. + Copyright © 2007-14 Asko Kauppi, Benoit Germain. All rights reserved.
Lua Lanes is published under the same MIT license as Lua 5.1 and 5.2.

- This document was revised on 20-Dec-13, and applies to version 3.7.5. + This document was revised on 06-Jan-14, and applies to version 3.7.6.

@@ -356,13 +356,17 @@ If provided, will be called in every created Lua state (keepers and lanes) right after initializing the base libraries. -
+
Typical usage is twofold: That way, all changes in the state can be properly taken into account when building the function lookup database. Default is nil. +
+ (Since version 3.7.6) If on_state_create() is a Lua function, it will be transfered normally before the call. +
+ If it is a C function, a C closure will be reconstructed in the created state from the C pointer. Lanes will raise an error if the function has upvalues. diff --git a/src/lanes.c b/src/lanes.c index e66342d..3ccf915 100644 --- a/src/lanes.c +++ b/src/lanes.c @@ -1,6 +1,6 @@ /* * LANES.C Copyright (c) 2007-08, Asko Kauppi - * Copyright (C) 2009-13, Benoit Germain + * Copyright (C) 2009-14, Benoit Germain * * Multithreading in Lua. * @@ -52,13 +52,13 @@ * ... */ -char const* VERSION = "3.7.5"; +char const* VERSION = "3.7.6"; /* =============================================================================== Copyright (C) 2007-10 Asko Kauppi - 2011-13 Benoit Germain + 2011-14 Benoit Germain Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1987,14 +1987,13 @@ LUAG_FUNC( thread_new) struct s_lane** ud; char const* libs = lua_tostring( L, 2); - int const on_state_create = lua_isfunction( L, 3) ? 3 : 0; - uint_t cs = luaG_optunsigned( L, 4, 0); - int const prio = (int) luaL_optinteger( L, 5, 0); - uint_t glob = lua_isnoneornil( L, 6) ? 0 : 6; - uint_t package = lua_isnoneornil( L,7) ? 0 : 7; - uint_t required = lua_isnoneornil( L, 8) ? 0 : 8; - -#define FIXED_ARGS 8 + uint_t cs = luaG_optunsigned( L, 3, 0); + int const prio = (int) luaL_optinteger( L, 4, 0); + uint_t glob = lua_isnoneornil( L, 5) ? 0 : 5; + uint_t package = lua_isnoneornil( L, 6) ? 0 : 6; + uint_t required = lua_isnoneornil( L, 7) ? 0 : 7; + +#define FIXED_ARGS 7 uint_t args = lua_gettop(L) - FIXED_ARGS; // public Lanes API accepts a generic range -3/+3 @@ -2011,7 +2010,7 @@ LUAG_FUNC( thread_new) // populate with selected libraries at the same time // - L2 = luaG_newstate( L, on_state_create, libs); + L2 = luaG_newstate( L, libs); STACK_GROW( L, 2); STACK_GROW( L2, 3); @@ -2727,6 +2726,8 @@ static const struct luaL_Reg lanes_functions [] = { */ static void init_once_LOCKED( lua_State* L) { + initialize_on_state_create( L); + STACK_CHECK( L); lua_getfield( L, 1, "verbose_errors"); diff --git a/src/lanes.lua b/src/lanes.lua index 4856a2d..0c544bb 100644 --- a/src/lanes.lua +++ b/src/lanes.lua @@ -297,7 +297,7 @@ local function gen( ... ) -- Lane generator -- return function(...) - return thread_new( func, libs, settings.on_state_create, cs, prio, g_tbl, package_tbl, required, ...) -- args + return thread_new( func, libs, cs, prio, g_tbl, package_tbl, required, ...) -- args end end diff --git a/src/threading.c b/src/threading.c index db9f734..3014136 100644 --- a/src/threading.c +++ b/src/threading.c @@ -1,6 +1,6 @@ /* * THREADING.C Copyright (c) 2007-08, Asko Kauppi - * Copyright (C) 2009-13, Benoit Germain + * Copyright (C) 2009-14, Benoit Germain * * Lua Lanes OS threading specific code. * @@ -12,7 +12,7 @@ =============================================================================== Copyright (C) 2007-10 Asko Kauppi -Copyright (C) 2009-13, Benoit Germain +Copyright (C) 2009-14, Benoit Germain Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/tools.c b/src/tools.c index 60f9012..9f36858 100644 --- a/src/tools.c +++ b/src/tools.c @@ -8,7 +8,7 @@ =============================================================================== Copyright (C) 2002-10 Asko Kauppi - 2011-13 benoit Germain + 2011-14 benoit Germain Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -161,6 +161,39 @@ void luaG_dump( lua_State* L ) { fprintf( stderr, "\n" ); } +static lua_CFunction s_on_state_create_func = NULL; +int initialize_on_state_create( lua_State* L) +{ + STACK_CHECK( L); + lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil + if( !lua_isnil( L, -1)) + { + // store C function pointer in an internal variable + s_on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create + if( s_on_state_create_func != NULL) + { + // make sure the function doesn't have upvalues + char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? + if( upname != NULL) // should be "" for C functions with upvalues if any + { + luaL_error( L, "on_state_create shouldn't have upvalues"); + } + // remove this C function from the config table so that it doesn't cause problems + // when we transfer the config table in newly created Lua states + lua_pushnil( L); // settings on_state_create nil + lua_setfield( L, -3, "on_state_create"); // settings on_state_create + } + else + { + // optim: store marker saying we have such a function in the config table + s_on_state_create_func = initialize_on_state_create; + } + } + lua_pop( L, 1); // settings + STACK_END( L, 0); + return 0; +} + // just like lua_xmove, args are (from, to) void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_) { @@ -569,7 +602,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) * Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. * */ -lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) +lua_State* luaG_newstate( lua_State* _from, char const* libs) { // reuse alloc function from the originating state #if PROPAGATE_ALLOCF @@ -587,7 +620,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // neither libs (not even 'base') nor special init func: we are done - if( libs == NULL && _on_state_create <= 0) + if( libs == NULL && s_on_state_create_func == NULL) { DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); return L; @@ -655,22 +688,19 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con STACK_CHECK( L); // call this after the base libraries are loaded and GC is restarted - if( _on_state_create > 0) + if( s_on_state_create_func != NULL) { DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); - if( lua_iscfunction( _from, _on_state_create)) + if( s_on_state_create_func != initialize_on_state_create) { // C function: recreate a closure in the new state, bypassing the lookup scheme - lua_CFunction osc = lua_tocfunction( _from, _on_state_create); - lua_pushcfunction( L, osc); + lua_pushcfunction( L, s_on_state_create_func); } - else + else // Lua function located in the config table { - STACK_CHECK( _from); - // Lua function: transfer as usual (should work as long as it only uses base libraries) - lua_pushvalue( _from, _on_state_create); - luaG_inter_move( _from, L, 1, eLM_LaneBody); - STACK_END( _from, 0); + lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); + lua_getfield( L, -1, "on_state_create"); + lua_remove( L, -2); } // capture error and forward it to main state if( lua_pcall( L, 0, 0, 0) != LUA_OK) diff --git a/src/tools.h b/src/tools.h index 19dca70..be358db 100644 --- a/src/tools.h +++ b/src/tools.h @@ -98,7 +98,7 @@ extern int debugspew_indent_depth; void luaG_dump( lua_State* L ); -lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs); +lua_State* luaG_newstate( lua_State* _from, char const* libs); void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_); typedef struct { @@ -129,6 +129,7 @@ extern MUTEX_T mtid_lock; void populate_func_lookup_table( lua_State* L, int _i, char const* _name); void serialize_require( lua_State *L); +int initialize_on_state_create( lua_State *L); extern MUTEX_T require_cs; // for verbose errors -- cgit v1.2.3-55-g6feb