Fix. Set Lua in callback context in info_read
function.
Fix. Support nested callbacks. Fix. Cleanup easy references when calls multi::close. Add. `__tostring` method for handles.
This commit is contained in:
parent
b2e9474c6b
commit
56b4d05c17
@ -46,6 +46,7 @@ script:
|
|||||||
- lunit.sh run.lua
|
- lunit.sh run.lua
|
||||||
- lua test_pause02.c.lua
|
- lua test_pause02.c.lua
|
||||||
- lua test_multi_callback.lua
|
- lua test_multi_callback.lua
|
||||||
|
- lua test_multi_nested_callback.lua.lua
|
||||||
# - lunit.sh test_easy.lua
|
# - lunit.sh test_easy.lua
|
||||||
# - lunit.sh test_safe.lua
|
# - lunit.sh test_safe.lua
|
||||||
# - lunit.sh test_form.lua
|
# - lunit.sh test_form.lua
|
||||||
|
@ -57,6 +57,7 @@ test_script:
|
|||||||
- lua run.lua
|
- lua run.lua
|
||||||
- lua test_pause02.c.lua
|
- lua test_pause02.c.lua
|
||||||
- lua test_multi_callback.lua
|
- lua test_multi_callback.lua
|
||||||
|
- lua test_multi_nested_callback.lua
|
||||||
|
|
||||||
after_test:
|
after_test:
|
||||||
- cd %APPVEYOR_BUILD_FOLDER%
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
|
76
src/lceasy.c
76
src/lceasy.c
@ -28,6 +28,31 @@ static const char *LCURL_EASY = LCURL_EASY_NAME;
|
|||||||
# define LCURL_E_UNKNOWN_OPTION CURLE_UNKNOWN_TELNET_OPTION
|
# define LCURL_E_UNKNOWN_OPTION CURLE_UNKNOWN_TELNET_OPTION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Before call curl_XXX function which can call any callback
|
||||||
|
* need set Curren Lua thread pointer in easy/multi contexts.
|
||||||
|
* But it also possible that we already in callback call.
|
||||||
|
* E.g. `curl_easy_pause` function may be called from write callback.
|
||||||
|
* and it even may be called in different thread.
|
||||||
|
* ```Lua
|
||||||
|
* multi:add_handle(easy)
|
||||||
|
* easy:setopt_writefunction(function(...)
|
||||||
|
* coroutine.wrap(function() multi:add_handle(easy2) end)()
|
||||||
|
* end)
|
||||||
|
* ```
|
||||||
|
* So we have to restore previews Lua state in callback contexts.
|
||||||
|
*/
|
||||||
|
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi){
|
||||||
|
if(p->multi && assign_multi){
|
||||||
|
lcurl__multi_assign_lua(L, p->multi, value, 1);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
p->L = value;
|
||||||
|
if(p->post){
|
||||||
|
p->post->L = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//{
|
//{
|
||||||
|
|
||||||
int lcurl_easy_create(lua_State *L, int error_mode){
|
int lcurl_easy_create(lua_State *L, int error_mode){
|
||||||
@ -72,24 +97,25 @@ lcurl_easy_t *lcurl_geteasy_at(lua_State *L, int i){
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lcurl_easy_to_s(lua_State *L){
|
||||||
|
lcurl_easy_t *p = (lcurl_easy_t *)lutil_checkudatap (L, 1, LCURL_EASY);
|
||||||
|
lua_pushfstring(L, LCURL_PREFIX " Easy (%p)", (void*)p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int lcurl_easy_cleanup(lua_State *L){
|
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->curl){
|
if(p->curl){
|
||||||
p->L = L;
|
lua_State *curL;
|
||||||
if(p->post){
|
|
||||||
p->post->L = L;
|
|
||||||
}
|
|
||||||
// In my tests when I cleanup some easy handle.
|
// In my tests when I cleanup some easy handle.
|
||||||
// timerfunction called only for single multi handle.
|
// timerfunction called only for single multi handle.
|
||||||
if(p->multi){
|
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
|
||||||
p->multi->L = L;
|
|
||||||
}
|
|
||||||
curl_easy_cleanup(p->curl);
|
curl_easy_cleanup(p->curl);
|
||||||
if(p->multi){
|
lcurl__easy_assign_lua(L, p, curL, 1);
|
||||||
p->multi->L = NULL;
|
|
||||||
}
|
|
||||||
p->curl = NULL;
|
p->curl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,18 +153,17 @@ static int lcurl_easy_cleanup(lua_State *L){
|
|||||||
static int lcurl_easy_perform(lua_State *L){
|
static int lcurl_easy_perform(lua_State *L){
|
||||||
lcurl_easy_t *p = lcurl_geteasy(L);
|
lcurl_easy_t *p = lcurl_geteasy(L);
|
||||||
CURLcode code;
|
CURLcode code;
|
||||||
|
lua_State *curL;
|
||||||
int top = 1;
|
int top = 1;
|
||||||
lua_settop(L, top);
|
lua_settop(L, top);
|
||||||
|
|
||||||
assert(p->rbuffer.ref == LUA_NOREF);
|
assert(p->rbuffer.ref == LUA_NOREF);
|
||||||
|
|
||||||
// store reference to current coroutine to callbacks
|
// store reference to current coroutine to callbacks
|
||||||
p->L = L;
|
// User should not call `perform` if handle assign to multi
|
||||||
if(p->post){
|
curL = p->L; lcurl__easy_assign_lua(L, p, L, 0);
|
||||||
p->post->L = L;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = curl_easy_perform(p->curl);
|
code = curl_easy_perform(p->curl);
|
||||||
|
lcurl__easy_assign_lua(L, p, curL, 0);
|
||||||
|
|
||||||
if(p->rbuffer.ref != LUA_NOREF){
|
if(p->rbuffer.ref != LUA_NOREF){
|
||||||
luaL_unref(L, LCURL_LUA_REGISTRY, p->rbuffer.ref);
|
luaL_unref(L, LCURL_LUA_REGISTRY, p->rbuffer.ref);
|
||||||
@ -744,6 +769,7 @@ static size_t lcurl_write_callback_(lua_State*L,
|
|||||||
|
|
||||||
static size_t lcurl_write_callback(char *ptr, size_t size, size_t nmemb, void *arg){
|
static size_t lcurl_write_callback(char *ptr, size_t size, size_t nmemb, void *arg){
|
||||||
lcurl_easy_t *p = arg;
|
lcurl_easy_t *p = arg;
|
||||||
|
assert(NULL != p->L);
|
||||||
return lcurl_write_callback_(p->L, p, &p->wr, ptr, size, nmemb);
|
return lcurl_write_callback_(p->L, p, &p->wr, ptr, size, nmemb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,11 +873,13 @@ static size_t lcurl_easy_read_callback(char *buffer, size_t size, size_t nitems,
|
|||||||
if(p->magic == LCURL_HPOST_STREAM_MAGIC){
|
if(p->magic == LCURL_HPOST_STREAM_MAGIC){
|
||||||
return lcurl_hpost_read_callback(buffer, size, nitems, arg);
|
return lcurl_hpost_read_callback(buffer, size, nitems, arg);
|
||||||
}
|
}
|
||||||
|
assert(NULL != p->L);
|
||||||
return lcurl_read_callback(p->L, &p->rd, &p->rbuffer, buffer, size, nitems);
|
return lcurl_read_callback(p->L, &p->rd, &p->rbuffer, buffer, size, nitems);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t lcurl_hpost_read_callback(char *buffer, size_t size, size_t nitems, void *arg){
|
static size_t lcurl_hpost_read_callback(char *buffer, size_t size, size_t nitems, void *arg){
|
||||||
lcurl_hpost_stream_t *p = arg;
|
lcurl_hpost_stream_t *p = arg;
|
||||||
|
assert(NULL != p->L);
|
||||||
return lcurl_read_callback(*p->L, &p->rd, &p->rbuffer, buffer, size, nitems);
|
return lcurl_read_callback(*p->L, &p->rd, &p->rbuffer, buffer, size, nitems);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,6 +897,7 @@ static int lcurl_easy_set_READFUNCTION(lua_State *L){
|
|||||||
|
|
||||||
static size_t lcurl_header_callback(char *ptr, size_t size, size_t nmemb, void *arg){
|
static size_t lcurl_header_callback(char *ptr, size_t size, size_t nmemb, void *arg){
|
||||||
lcurl_easy_t *p = arg;
|
lcurl_easy_t *p = arg;
|
||||||
|
assert(NULL != p->L);
|
||||||
return lcurl_write_callback_(p->L, p, &p->hd, ptr, size, nmemb);
|
return lcurl_write_callback_(p->L, p, &p->hd, ptr, size, nmemb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -889,10 +918,12 @@ static int lcurl_xferinfo_callback(void *arg, curl_off_t dltotal, curl_off_t dln
|
|||||||
{
|
{
|
||||||
lcurl_easy_t *p = arg;
|
lcurl_easy_t *p = arg;
|
||||||
lua_State *L = p->L;
|
lua_State *L = p->L;
|
||||||
|
int n, top, ret = 0;
|
||||||
|
|
||||||
int ret = 0;
|
assert(NULL != p->L);
|
||||||
int top = lua_gettop(L);
|
|
||||||
int n = lcurl_util_push_cb(L, &p->pr);
|
top = lua_gettop(L);
|
||||||
|
n = lcurl_util_push_cb(L, &p->pr);
|
||||||
|
|
||||||
lua_pushnumber( L, (lua_Number)dltotal );
|
lua_pushnumber( L, (lua_Number)dltotal );
|
||||||
lua_pushnumber( L, (lua_Number)dlnow );
|
lua_pushnumber( L, (lua_Number)dlnow );
|
||||||
@ -1033,8 +1064,14 @@ static int lcurl_easy_getinfo(lua_State *L){
|
|||||||
|
|
||||||
static int lcurl_easy_pause(lua_State *L){
|
static int lcurl_easy_pause(lua_State *L){
|
||||||
lcurl_easy_t *p = lcurl_geteasy(L);
|
lcurl_easy_t *p = lcurl_geteasy(L);
|
||||||
|
lua_State *curL;
|
||||||
int mask = luaL_checkint(L, 2);
|
int mask = luaL_checkint(L, 2);
|
||||||
CURLcode code = curl_easy_pause(p->curl, mask);
|
CURLcode code;
|
||||||
|
|
||||||
|
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
|
||||||
|
code = curl_easy_pause(p->curl, mask);
|
||||||
|
lcurl__easy_assign_lua(L, p, curL, 1);
|
||||||
|
|
||||||
if(code != CURLE_OK){
|
if(code != CURLE_OK){
|
||||||
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
|
||||||
}
|
}
|
||||||
@ -1106,6 +1143,7 @@ static const struct luaL_Reg lcurl_easy_methods[] = {
|
|||||||
{ "perform", lcurl_easy_perform },
|
{ "perform", lcurl_easy_perform },
|
||||||
{ "close", lcurl_easy_cleanup },
|
{ "close", lcurl_easy_cleanup },
|
||||||
{ "__gc", lcurl_easy_cleanup },
|
{ "__gc", lcurl_easy_cleanup },
|
||||||
|
{ "__tostring", lcurl_easy_to_s },
|
||||||
|
|
||||||
{ "setdata", lcurl_easy_setdata },
|
{ "setdata", lcurl_easy_setdata },
|
||||||
{ "getdata", lcurl_easy_getdata },
|
{ "getdata", lcurl_easy_getdata },
|
||||||
|
@ -65,4 +65,6 @@ lcurl_easy_t *lcurl_geteasy_at(lua_State *L, int i);
|
|||||||
|
|
||||||
void lcurl_easy_initlib(lua_State *L, int nup);
|
void lcurl_easy_initlib(lua_State *L, int nup);
|
||||||
|
|
||||||
|
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,22 +28,19 @@
|
|||||||
#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;
|
||||||
|
|
||||||
static void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, int assign_easy){
|
void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, lua_State *value, int assign_easy){
|
||||||
p->L = L;
|
if((assign_easy)&&(p->L != value)){
|
||||||
|
|
||||||
if(assign_easy){
|
|
||||||
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
while(lua_next(L, -2)){
|
while(lua_next(L, -2)){
|
||||||
lcurl_easy_t *e = lcurl_geteasy_at(L, -1);
|
lcurl_easy_t *e = lcurl_geteasy_at(L, -1);
|
||||||
e->L = L;
|
lcurl__easy_assign_lua(L, e, value, 0);
|
||||||
if(e->post){
|
|
||||||
e->post->L = L;
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->L = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//{
|
//{
|
||||||
@ -78,6 +75,12 @@ lcurl_multi_t *lcurl_getmulti_at(lua_State *L, int i){
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lcurl_multi_to_s(lua_State *L){
|
||||||
|
lcurl_multi_t *p = (lcurl_multi_t *)lutil_checkudatap (L, 1, LCURL_MULTI);
|
||||||
|
lua_pushfstring(L, LCURL_PREFIX " Multi (%p)", (void*)p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int lcurl_multi_cleanup(lua_State *L){
|
static int lcurl_multi_cleanup(lua_State *L){
|
||||||
lcurl_multi_t *p = lcurl_getmulti(L);
|
lcurl_multi_t *p = lcurl_getmulti(L);
|
||||||
if(p->curl){
|
if(p->curl){
|
||||||
@ -86,6 +89,14 @@ static int lcurl_multi_cleanup(lua_State *L){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(p->h_ref != LUA_NOREF){
|
if(p->h_ref != LUA_NOREF){
|
||||||
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
|
lua_pushnil(L);
|
||||||
|
while(lua_next(L, -2)){
|
||||||
|
lcurl_easy_t *e = lcurl_geteasy_at(L, -1);
|
||||||
|
e->multi = NULL;
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
luaL_unref(L, LCURL_LUA_REGISTRY, p->h_ref);
|
luaL_unref(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
p->h_ref = LUA_NOREF;
|
p->h_ref = LUA_NOREF;
|
||||||
}
|
}
|
||||||
@ -108,6 +119,7 @@ static int lcurl_multi_add_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;
|
CURLMcode code;
|
||||||
|
lua_State *curL;
|
||||||
|
|
||||||
if(e->multi){
|
if(e->multi){
|
||||||
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI,
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI,
|
||||||
@ -135,9 +147,9 @@ static int lcurl_multi_add_handle(lua_State *L){
|
|||||||
|
|
||||||
e->multi = p;
|
e->multi = p;
|
||||||
|
|
||||||
lcurl__multi_assign_lua(L, p, 0);
|
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);
|
||||||
p->L = NULL;
|
lcurl__multi_assign_lua(L, p, curL, 1);
|
||||||
|
|
||||||
if(code != CURLM_OK){
|
if(code != CURLM_OK){
|
||||||
// remove
|
// remove
|
||||||
@ -155,6 +167,7 @@ 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;
|
CURLMcode code;
|
||||||
|
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.
|
||||||
@ -163,9 +176,9 @@ static int lcurl_multi_remove_handle(lua_State *L){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcurl__multi_assign_lua(L, p, 0);
|
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);
|
||||||
p->L = NULL;
|
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);
|
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
|
||||||
@ -183,10 +196,11 @@ static int lcurl_multi_perform(lua_State *L){
|
|||||||
lcurl_multi_t *p = lcurl_getmulti(L);
|
lcurl_multi_t *p = lcurl_getmulti(L);
|
||||||
int running_handles = 0;
|
int running_handles = 0;
|
||||||
CURLMcode code;
|
CURLMcode code;
|
||||||
|
lua_State *curL;
|
||||||
|
|
||||||
lcurl__multi_assign_lua(L, p, 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);
|
||||||
p->L = NULL;
|
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);
|
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
|
||||||
@ -213,7 +227,14 @@ static int lcurl_multi_info_read(lua_State *L){
|
|||||||
e = lcurl_geteasy_at(L, -1);
|
e = lcurl_geteasy_at(L, -1);
|
||||||
if(remove){
|
if(remove){
|
||||||
//! @fixme We ignore any errors
|
//! @fixme We ignore any errors
|
||||||
if(CURLM_OK == curl_multi_remove_handle(p->curl, e->curl)){
|
CURLMcode code;
|
||||||
|
lua_State *curL;
|
||||||
|
|
||||||
|
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
|
||||||
|
code = curl_multi_remove_handle(p->curl, e->curl);
|
||||||
|
lcurl__multi_assign_lua(L, p, curL, 1);
|
||||||
|
|
||||||
|
if(CURLM_OK == code){
|
||||||
e->multi = NULL;
|
e->multi = NULL;
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_rawsetp(L, -3, e->curl);
|
lua_rawsetp(L, -3, e->curl);
|
||||||
@ -309,12 +330,14 @@ static int lcurl_multi_socket_action(lua_State *L){
|
|||||||
lcurl_multi_t *p = lcurl_getmulti(L);
|
lcurl_multi_t *p = lcurl_getmulti(L);
|
||||||
curl_socket_t s = lutil_optint64(L, 2, CURL_SOCKET_TIMEOUT);
|
curl_socket_t s = lutil_optint64(L, 2, CURL_SOCKET_TIMEOUT);
|
||||||
CURLMcode code; int n, mask;
|
CURLMcode code; int n, mask;
|
||||||
|
lua_State *curL;
|
||||||
|
|
||||||
if(s == CURL_SOCKET_TIMEOUT) mask = lutil_optint64(L, 3, 0);
|
if(s == CURL_SOCKET_TIMEOUT) mask = lutil_optint64(L, 3, 0);
|
||||||
else mask = lutil_checkint64(L, 3);
|
else mask = lutil_checkint64(L, 3);
|
||||||
|
|
||||||
lcurl__multi_assign_lua(L, p, 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);
|
||||||
p->L = NULL;
|
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);
|
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
|
||||||
@ -415,10 +438,12 @@ static int lcurl_multi_set_callback(lua_State *L,
|
|||||||
int lcurl_multi_timer_callback(CURLM *multi, long ms, void *arg){
|
int lcurl_multi_timer_callback(CURLM *multi, long ms, void *arg){
|
||||||
lcurl_multi_t *p = arg;
|
lcurl_multi_t *p = arg;
|
||||||
lua_State *L = p->L;
|
lua_State *L = p->L;
|
||||||
|
int n, top, ret = 0;
|
||||||
|
|
||||||
int ret = 0;
|
assert(NULL != p->L);
|
||||||
int top = lua_gettop(L);
|
|
||||||
int n = lcurl_util_push_cb(L, &p->tm);
|
top = lua_gettop(L);
|
||||||
|
n = lcurl_util_push_cb(L, &p->tm);
|
||||||
|
|
||||||
lua_pushnumber(L, ms);
|
lua_pushnumber(L, ms);
|
||||||
if(lua_pcall(L, n, LUA_MULTRET, 0)){
|
if(lua_pcall(L, n, LUA_MULTRET, 0)){
|
||||||
@ -460,8 +485,11 @@ static int lcurl_multi_socket_callback(CURL *easy, curl_socket_t s, int what, vo
|
|||||||
lcurl_multi_t *p = arg;
|
lcurl_multi_t *p = arg;
|
||||||
lua_State *L = p->L;
|
lua_State *L = p->L;
|
||||||
lcurl_easy_t *e;
|
lcurl_easy_t *e;
|
||||||
int n, top = lua_gettop(L);
|
int n, top;
|
||||||
|
|
||||||
|
assert(NULL != p->L);
|
||||||
|
|
||||||
|
top = lua_gettop(L);
|
||||||
n = lcurl_util_push_cb(L, &p->sc);
|
n = lcurl_util_push_cb(L, &p->sc);
|
||||||
|
|
||||||
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
|
||||||
@ -547,6 +575,7 @@ static const struct luaL_Reg lcurl_multi_methods[] = {
|
|||||||
{"wait", lcurl_multi_wait },
|
{"wait", lcurl_multi_wait },
|
||||||
{"timeout", lcurl_multi_timeout },
|
{"timeout", lcurl_multi_timeout },
|
||||||
{"socket_action", lcurl_multi_socket_action },
|
{"socket_action", lcurl_multi_socket_action },
|
||||||
|
{ "__tostring", lcurl_multi_to_s },
|
||||||
|
|
||||||
#define OPT_ENTRY(L, N, T, S) { "setopt_"#L, lcurl_multi_set_##N },
|
#define OPT_ENTRY(L, N, T, S) { "setopt_"#L, lcurl_multi_set_##N },
|
||||||
#include "lcoptmulti.h"
|
#include "lcoptmulti.h"
|
||||||
|
@ -31,4 +31,6 @@ lcurl_multi_t *lcurl_getmulti_at(lua_State *L, int i);
|
|||||||
|
|
||||||
void lcurl_multi_initlib(lua_State *L, int nup);
|
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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,6 +43,12 @@ lcurl_share_t *lcurl_getshare_at(lua_State *L, int i){
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lcurl_easy_to_s(lua_State *L){
|
||||||
|
lcurl_share_t *p = (lcurl_share_t *)lutil_checkudatap (L, 1, LCURL_SHARE);
|
||||||
|
lua_pushfstring(L, LCURL_PREFIX " Share (%p)", (void*)p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int lcurl_share_cleanup(lua_State *L){
|
static int lcurl_share_cleanup(lua_State *L){
|
||||||
lcurl_share_t *p = lcurl_getshare(L);
|
lcurl_share_t *p = lcurl_getshare(L);
|
||||||
if(p->curl){
|
if(p->curl){
|
||||||
@ -113,6 +119,7 @@ static int lcurl_share_setopt(lua_State *L){
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
static const struct luaL_Reg lcurl_share_methods[] = {
|
static const struct luaL_Reg lcurl_share_methods[] = {
|
||||||
|
{ "__tostring", lcurl_easy_to_s },
|
||||||
{"setopt", lcurl_share_setopt },
|
{"setopt", lcurl_share_setopt },
|
||||||
|
|
||||||
#define OPT_ENTRY(L, N, T, S) { "setopt_"#L, lcurl_share_set_##N },
|
#define OPT_ENTRY(L, N, T, S) { "setopt_"#L, lcurl_share_set_##N },
|
||||||
|
47
test/test_multi_nested_callback.lua
Normal file
47
test/test_multi_nested_callback.lua
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
local curl = require "lcurl"
|
||||||
|
|
||||||
|
-- for Lua 5.1 compat
|
||||||
|
local function co_running()
|
||||||
|
local co, main = coroutine.running()
|
||||||
|
if main == true then return nil end
|
||||||
|
return co
|
||||||
|
end
|
||||||
|
|
||||||
|
local state, called = true, 0
|
||||||
|
local thread, msg
|
||||||
|
|
||||||
|
local function check_thread()
|
||||||
|
if thread ~= co_running() then
|
||||||
|
print(msg)
|
||||||
|
os.exit(-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local m; m = curl.multi{
|
||||||
|
timerfunction = function()
|
||||||
|
check_thread()
|
||||||
|
called = called + 1
|
||||||
|
|
||||||
|
if state then state = false
|
||||||
|
thread = coroutine.create(function()
|
||||||
|
local e = curl.easy()
|
||||||
|
m:add_handle(e)
|
||||||
|
end)
|
||||||
|
|
||||||
|
msg = 'add from coroutine'
|
||||||
|
coroutine.resume(thread)
|
||||||
|
assert(called == 2)
|
||||||
|
|
||||||
|
msg, thread = 'add from main'
|
||||||
|
local e = curl.easy()
|
||||||
|
m:add_handle(e)
|
||||||
|
assert(called == 3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
e = curl.easy()
|
||||||
|
|
||||||
|
m:add_handle(e)
|
||||||
|
|
||||||
|
assert(called == 3)
|
Loading…
x
Reference in New Issue
Block a user