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.
```
This commit is contained in:
Alexey Melnichuk 2014-09-01 16:19:51 +05:00
parent ee905b4209
commit 21106ca7bd
4 changed files with 85 additions and 15 deletions

View File

@ -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;

View File

@ -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, 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, 3);
lua_pop(L, 1);
}
lua_pop(L, 2);
return list;
}

View File

@ -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);

View File

@ -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