From 21106ca7bdf63453c3df9377d6d84d7adb546108 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Mon, 1 Sep 2014 16:19:51 +0500 Subject: [PATCH] Fix. Reset options will also reset value in storage. ```Lua -- Fixed e:setopt_httppost(curl.form()) e:setopt_httppost(curl.form()) -- `e` store 2 form object and the will alive until `e` is alive. ``` --- src/lceasy.c | 8 +++---- src/lcutils.c | 52 ++++++++++++++++++++++++++++++++++++---------- src/lcutils.h | 4 ++++ test/test_easy.lua | 36 ++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/lceasy.c b/src/lceasy.c index 3bc84b0..3c3d9e1 100644 --- a/src/lceasy.c +++ b/src/lceasy.c @@ -201,7 +201,7 @@ static int lcurl_opt_set_string_(lua_State *L, int opt, int store){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code); } - if(store)lcurl_storage_preserve_value(L, p->storage, 2); + if(store)lcurl_storage_preserve_iv(L, p->storage, opt, 2); lua_settop(L, 1); return 1; @@ -264,7 +264,7 @@ static int lcurl_easy_set_POSTFIELDS(lua_State *L){ if(code != CURLE_OK){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code); } - lcurl_storage_preserve_value(L, p->storage, 2); + lcurl_storage_preserve_iv(L, p->storage, CURLOPT_POSTFIELDS, 2); code = curl_easy_setopt(p->curl, CURLOPT_POSTFIELDSIZE, (long)len); if(code != CURLE_OK){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code); @@ -285,7 +285,7 @@ static int lcurl_easy_set_HTTPPOST(lua_State *L){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code); } - lcurl_storage_preserve_value(L, p->storage, 2); + lcurl_storage_preserve_iv(L, p->storage, CURLOPT_HTTPPOST, 2); lua_settop(L, 1); return 1; @@ -299,7 +299,7 @@ static int lcurl_easy_set_SHARE(lua_State *L){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code); } - lcurl_storage_preserve_value(L, p->storage, 2); + lcurl_storage_preserve_iv(L, p->storage, CURLOPT_SHARE, 2); lua_settop(L, 1); return 1; diff --git a/src/lcutils.c b/src/lcutils.c index de81346..84a695e 100644 --- a/src/lcutils.c +++ b/src/lcutils.c @@ -2,6 +2,9 @@ #include "lcutils.h" #include "lcerror.h" +#define LCURL_STORAGE_SLIST 1 +#define LCURL_STORAGE_KV 2 + int lcurl_storage_init(lua_State *L){ lua_newtable(L); return luaL_ref(L, LCURL_LUA_REGISTRY); @@ -15,32 +18,59 @@ void lcurl_storage_preserve_value(lua_State *L, int storage, int i){ lua_pop(L, 1); } -int lcurl_storage_preserve_slist(lua_State *L, int storage, struct curl_slist * list){ - int r; - lua_rawgeti(L, LCURL_LUA_REGISTRY, storage); - lua_rawgeti(L, -1, 1); // list storage +static void lcurl_storage_ensure_t(lua_State *L, int t){ + lua_rawgeti(L, -1, t); if(!lua_istable(L, -1)){ lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, -1); - lua_rawseti(L, -3, 1); + lua_rawseti(L, -3, LCURL_STORAGE_SLIST); } +} + +int lcurl_storage_preserve_slist(lua_State *L, int storage, struct curl_slist * list){ + int r; + lua_rawgeti(L, LCURL_LUA_REGISTRY, storage); + lcurl_storage_ensure_t(L, LCURL_STORAGE_SLIST); lua_pushlightuserdata(L, list); r = luaL_ref(L, -2); lua_pop(L, 2); return r; } +void lcurl_storage_preserve_iv(lua_State *L, int storage, int i, int v){ + v = lua_absindex(L, v); + + lua_rawgeti(L, LCURL_LUA_REGISTRY, storage); + lcurl_storage_ensure_t(L, LCURL_STORAGE_KV); + lua_pushvalue(L, v); + lua_rawseti(L, -2, i); + lua_pop(L, 2); +} + +void lcurl_storage_remove_i(lua_State *L, int storage, int i){ + lua_rawgeti(L, LCURL_LUA_REGISTRY, storage); + lua_rawgeti(L, -1, LCURL_STORAGE_KV); + if(lua_istable(L, -1)){ + lua_pushnil(L); + lua_rawseti(L, -3, i); + } + lua_pop(L, 2); +} + struct curl_slist* lcurl_storage_remove_slist(lua_State *L, int storage, int idx){ struct curl_slist* list; assert(idx != LUA_NOREF); lua_rawgeti(L, LCURL_LUA_REGISTRY, storage); - lua_rawgeti(L, -1, 1); // list storage - lua_rawgeti(L, -1, idx); - list = lua_touserdata(L, -1); - assert(list); - luaL_unref(L, -2, idx); - lua_pop(L, 3); + lua_rawgeti(L, -1, LCURL_STORAGE_SLIST); // list storage + if(lua_istable(L, -1)){ + lua_rawgeti(L, -1, idx); + list = lua_touserdata(L, -1); + assert(list); + luaL_unref(L, -2, idx); + lua_pop(L, 1); + } + lua_pop(L, 2); return list; } diff --git a/src/lcutils.h b/src/lcutils.h index 1ef1e24..67c1c2e 100644 --- a/src/lcutils.h +++ b/src/lcutils.h @@ -24,6 +24,10 @@ int lcurl_storage_preserve_slist(lua_State *L, int storage, struct curl_slist * struct curl_slist* lcurl_storage_remove_slist(lua_State *L, int storage, int idx); +void lcurl_storage_preserve_iv(lua_State *L, int storage, int i, int v); + +void lcurl_storage_remove_i(lua_State *L, int storage, int i); + int lcurl_storage_free(lua_State *L, int storage); struct curl_slist* lcurl_util_array_to_slist(lua_State *L, int t); diff --git a/test/test_easy.lua b/test/test_easy.lua index 643b6a3..04b07c7 100644 --- a/test/test_easy.lua +++ b/test/test_easy.lua @@ -8,6 +8,15 @@ local scurl = require "lcurl.safe" local url = "http://example.com" local fname = "./test.download" +local function weak_ptr(val) + return setmetatable({value = val},{__mode = 'v'}) +end + +local function gc_collect() + collectgarbage("collect") + collectgarbage("collect") +end + local _ENV = TEST_CASE'write_callback' do local c, f @@ -64,6 +73,33 @@ end end +local _ENV = TEST_CASE'setopt_form' do + +local c + +function teardown() + if c then c:close() end + c = nil +end + +function test() + local pfrom, e + do + local form = curl.form() + e = curl.easy{httppost = form} + pfrom = weak_ptr(form) + end + + gc_collect() + assert(pfrom.value) + + e:setopt_httppost(curl.form()) + + gc_collect() + assert(not pfrom.value) +end + +end