Fix. easy:close removes self from multi handle.

Change. Do not reset Lua state back to NULL.
This commit is contained in:
Alexey Melnichuk 2016-09-28 15:52:22 +03:00
parent 367eb1482f
commit 78a4a03e23
4 changed files with 90 additions and 13 deletions

View File

@ -4,6 +4,7 @@ INITLAKEFILE()
DEFINES = L{DEFINES, DEFINES = L{DEFINES,
IF(WINDOWS, 'DLL_EXPORT', ''); IF(WINDOWS, 'DLL_EXPORT', '');
IF(DEBUG, 'LCURL_RESET_NULL_LUA', '');
} }
cURL = c.shared{'lcurl', cURL = c.shared{'lcurl',
@ -30,6 +31,8 @@ target('test', install, function()
run_test('test_form.lua') run_test('test_form.lua')
run_test('test_pause02.c.lua') run_test('test_pause02.c.lua')
run_test('test_curl.lua') run_test('test_curl.lua')
run_test('test_multi_callback.lua')
run_test('test_multi_nested_callback.lua')
if not test_summary() then if not test_summary() then
quit("test fail") quit("test fail")

View File

@ -40,6 +40,8 @@ static const char *LCURL_EASY = LCURL_EASY_NAME;
* end) * end)
* ``` * ```
* So we have to restore previews Lua state in callback contexts. * So we have to restore previews Lua state in callback contexts.
* But if previews Lua state is NULL then we can just do not set it back.
* But set it to NULL make esier debug code.
*/ */
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi){ void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi){
if(p->multi && assign_multi){ if(p->multi && assign_multi){
@ -107,6 +109,12 @@ static int lcurl_easy_cleanup(lua_State *L){
lcurl_easy_t *p = lcurl_geteasy(L); lcurl_easy_t *p = lcurl_geteasy(L);
int i; int i;
if(p->multi){
CURLMcode code = lcurl__multi_remove_handle(L, p->multi, p);
//! @todo what I can do if I can not remove it???
}
if(p->curl){ if(p->curl){
lua_State *curL; lua_State *curL;
@ -114,6 +122,9 @@ static int lcurl_easy_cleanup(lua_State *L){
// timerfunction called only for single multi handle. // timerfunction called only for single multi handle.
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1); curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
curl_easy_cleanup(p->curl); curl_easy_cleanup(p->curl);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__easy_assign_lua(L, p, curL, 1); lcurl__easy_assign_lua(L, p, curL, 1);
p->curl = NULL; p->curl = NULL;
@ -163,6 +174,9 @@ static int lcurl_easy_perform(lua_State *L){
// User should not call `perform` if handle assign to multi // User should not call `perform` if handle assign to multi
curL = p->L; lcurl__easy_assign_lua(L, p, L, 0); curL = p->L; lcurl__easy_assign_lua(L, p, L, 0);
code = curl_easy_perform(p->curl); code = curl_easy_perform(p->curl);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__easy_assign_lua(L, p, curL, 0); lcurl__easy_assign_lua(L, p, curL, 0);
if(p->rbuffer.ref != LUA_NOREF){ if(p->rbuffer.ref != LUA_NOREF){
@ -1070,6 +1084,9 @@ static int lcurl_easy_pause(lua_State *L){
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1); curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
code = curl_easy_pause(p->curl, mask); code = curl_easy_pause(p->curl, mask);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__easy_assign_lua(L, p, curL, 1); lcurl__easy_assign_lua(L, p, curL, 1);
if(code != CURLE_OK){ if(code != CURLE_OK){

View File

@ -28,7 +28,35 @@
#define LCURL_MULTI_NAME LCURL_PREFIX" Multi" #define LCURL_MULTI_NAME LCURL_PREFIX" Multi"
static const char *LCURL_MULTI = LCURL_MULTI_NAME; static const char *LCURL_MULTI = LCURL_MULTI_NAME;
#if defined(DEBUG) || defined(_DEBUG)
static void lcurl__multi_validate_sate(lua_State *L, lcurl_multi_t *p){
int top = lua_gettop(L);
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
assert(lua_istable(L, -1));
lua_pushnil(L);
while(lua_next(L, -2)){
lcurl_easy_t *e = lcurl_geteasy_at(L, -1);
void *ptr = lua_touserdata(L, -2);
assert(e->curl == ptr);
assert(e->multi == p);
assert(e->L == p->L);
lua_pop(L, 1);
}
lua_pop(L, 1);
assert(lua_gettop(L) == top);
}
#else
# define lcurl__multi_validate_sate(L, p) (void*)(0)
#endif
void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, lua_State *value, int assign_easy){ void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, lua_State *value, int assign_easy){
lcurl__multi_validate_sate(L, p);
if((assign_easy)&&(p->L != value)){ if((assign_easy)&&(p->L != value)){
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref); lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
lua_pushnil(L); lua_pushnil(L);
@ -145,10 +173,16 @@ static int lcurl_multi_add_handle(lua_State *L){
lua_rawsetp(L, -2, e->curl); lua_rawsetp(L, -2, e->curl);
lua_settop(L, 1); lua_settop(L, 1);
// all `esay` handles have to have same L
lcurl__easy_assign_lua(L, e, p->L, 0);
e->multi = p; e->multi = p;
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1); curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
code = curl_multi_add_handle(p->curl, e->curl); code = curl_multi_add_handle(p->curl, e->curl);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__multi_assign_lua(L, p, curL, 1); lcurl__multi_assign_lua(L, p, curL, 1);
if(code != CURLM_OK){ if(code != CURLM_OK){
@ -166,30 +200,42 @@ static int lcurl_multi_add_handle(lua_State *L){
static int lcurl_multi_remove_handle(lua_State *L){ static int lcurl_multi_remove_handle(lua_State *L){
lcurl_multi_t *p = lcurl_getmulti(L); lcurl_multi_t *p = lcurl_getmulti(L);
lcurl_easy_t *e = lcurl_geteasy_at(L, 2); lcurl_easy_t *e = lcurl_geteasy_at(L, 2);
CURLMcode code = lcurl__multi_remove_handle(L, p, e);
if(code != CURLM_OK){
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
}
lua_settop(L, 1);
return 1;
}
CURLMcode lcurl__multi_remove_handle(lua_State *L, lcurl_multi_t *p, lcurl_easy_t *e){
CURLMcode code; CURLMcode code;
lua_State *curL; lua_State *curL;
if(e->multi != p){ if(e->multi != p){
// cURL returns CURLM_OK for such call so we do the same. // cURL returns CURLM_OK for such call so we do the same.
// tested on 7.37.1 // tested on 7.37.1
lua_settop(L, 1); return CURLM_OK;
return 1;
} }
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1); curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
code = curl_multi_remove_handle(p->curl, e->curl); code = curl_multi_remove_handle(p->curl, e->curl);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__multi_assign_lua(L, p, curL, 1); lcurl__multi_assign_lua(L, p, curL, 1);
if(code != CURLM_OK){ if(code == CURLM_OK){
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
}
e->multi = NULL; e->multi = NULL;
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref); lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
lua_pushnil(L); lua_pushnil(L);
lua_rawsetp(L, -2, e->curl); lua_rawsetp(L, -2, e->curl);
lua_settop(L, 1); lua_pop(L, 1);
return 1; }
return code;
} }
static int lcurl_multi_perform(lua_State *L){ static int lcurl_multi_perform(lua_State *L){
@ -200,6 +246,9 @@ static int lcurl_multi_perform(lua_State *L){
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1); curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
while((code = curl_multi_perform(p->curl, &running_handles)) == CURLM_CALL_MULTI_PERFORM); while((code = curl_multi_perform(p->curl, &running_handles)) == CURLM_CALL_MULTI_PERFORM);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__multi_assign_lua(L, p, curL, 1); lcurl__multi_assign_lua(L, p, curL, 1);
if(code != CURLM_OK){ if(code != CURLM_OK){
@ -232,6 +281,9 @@ static int lcurl_multi_info_read(lua_State *L){
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1); curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
code = curl_multi_remove_handle(p->curl, e->curl); code = curl_multi_remove_handle(p->curl, e->curl);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__multi_assign_lua(L, p, curL, 1); lcurl__multi_assign_lua(L, p, curL, 1);
if(CURLM_OK == code){ if(CURLM_OK == code){
@ -337,6 +389,9 @@ static int lcurl_multi_socket_action(lua_State *L){
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1); curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
code = curl_multi_socket_action(p->curl, s, mask, &n); code = curl_multi_socket_action(p->curl, s, mask, &n);
#ifndef LCURL_RESET_NULL_LUA
if(curL != NULL)
#endif
lcurl__multi_assign_lua(L, p, curL, 1); lcurl__multi_assign_lua(L, p, curL, 1);
if(code != CURLM_OK){ if(code != CURLM_OK){

View File

@ -33,4 +33,6 @@ void lcurl_multi_initlib(lua_State *L, int nup);
void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, lua_State *value, int assign_easy); void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, lua_State *value, int assign_easy);
CURLMcode lcurl__multi_remove_handle(lua_State *L, lcurl_multi_t *p, lcurl_easy_t *e);
#endif #endif