Skip to content

Commit 78a4a03

Browse files
committed
Fix. easy:close removes self from multi handle.
Change. Do not reset Lua state back to NULL.
1 parent 367eb14 commit 78a4a03

File tree

4 files changed

+90
-13
lines changed

4 files changed

+90
-13
lines changed

lakefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ PROJECT = 'cURL'
22

33
INITLAKEFILE()
44

5-
DEFINES = L{DEFINES,
5+
DEFINES = L{DEFINES,
66
IF(WINDOWS, 'DLL_EXPORT', '');
7+
IF(DEBUG, 'LCURL_RESET_NULL_LUA', '');
78
}
89

910
cURL = c.shared{'lcurl',
@@ -18,7 +19,7 @@ cURL = c.shared{'lcurl',
1819
target('build', cURL)
1920

2021
install = target('install', {
21-
file.group{odir=LIBDIR; src = cURL };
22+
file.group{odir=LIBDIR; src = cURL };
2223
file.group{odir=LIBDIR; src = J("src", "lua") ; recurse = true };
2324
file.group{odir=J(ROOT, 'examples'); src = 'examples'; recurse = true };
2425
file.group{odir=TESTDIR; src = 'test'; recurse = true };
@@ -30,6 +31,8 @@ target('test', install, function()
3031
run_test('test_form.lua')
3132
run_test('test_pause02.c.lua')
3233
run_test('test_curl.lua')
34+
run_test('test_multi_callback.lua')
35+
run_test('test_multi_nested_callback.lua')
3336

3437
if not test_summary() then
3538
quit("test fail")

src/lceasy.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ static const char *LCURL_EASY = LCURL_EASY_NAME;
4040
* end)
4141
* ```
4242
* So we have to restore previews Lua state in callback contexts.
43+
* But if previews Lua state is NULL then we can just do not set it back.
44+
* But set it to NULL make esier debug code.
4345
*/
4446
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi){
4547
if(p->multi && assign_multi){
@@ -107,13 +109,22 @@ static int lcurl_easy_cleanup(lua_State *L){
107109
lcurl_easy_t *p = lcurl_geteasy(L);
108110
int i;
109111

112+
if(p->multi){
113+
CURLMcode code = lcurl__multi_remove_handle(L, p->multi, p);
114+
115+
//! @todo what I can do if I can not remove it???
116+
}
117+
110118
if(p->curl){
111119
lua_State *curL;
112120

113121
// In my tests when I cleanup some easy handle.
114122
// timerfunction called only for single multi handle.
115123
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
116124
curl_easy_cleanup(p->curl);
125+
#ifndef LCURL_RESET_NULL_LUA
126+
if(curL != NULL)
127+
#endif
117128
lcurl__easy_assign_lua(L, p, curL, 1);
118129

119130
p->curl = NULL;
@@ -163,6 +174,9 @@ static int lcurl_easy_perform(lua_State *L){
163174
// User should not call `perform` if handle assign to multi
164175
curL = p->L; lcurl__easy_assign_lua(L, p, L, 0);
165176
code = curl_easy_perform(p->curl);
177+
#ifndef LCURL_RESET_NULL_LUA
178+
if(curL != NULL)
179+
#endif
166180
lcurl__easy_assign_lua(L, p, curL, 0);
167181

168182
if(p->rbuffer.ref != LUA_NOREF){
@@ -1070,6 +1084,9 @@ static int lcurl_easy_pause(lua_State *L){
10701084

10711085
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
10721086
code = curl_easy_pause(p->curl, mask);
1087+
#ifndef LCURL_RESET_NULL_LUA
1088+
if(curL != NULL)
1089+
#endif
10731090
lcurl__easy_assign_lua(L, p, curL, 1);
10741091

10751092
if(code != CURLE_OK){

src/lcmulti.c

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,35 @@
2828
#define LCURL_MULTI_NAME LCURL_PREFIX" Multi"
2929
static const char *LCURL_MULTI = LCURL_MULTI_NAME;
3030

31+
#if defined(DEBUG) || defined(_DEBUG)
32+
static void lcurl__multi_validate_sate(lua_State *L, lcurl_multi_t *p){
33+
int top = lua_gettop(L);
34+
35+
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
36+
assert(lua_istable(L, -1));
37+
38+
lua_pushnil(L);
39+
while(lua_next(L, -2)){
40+
lcurl_easy_t *e = lcurl_geteasy_at(L, -1);
41+
void *ptr = lua_touserdata(L, -2);
42+
43+
assert(e->curl == ptr);
44+
assert(e->multi == p);
45+
assert(e->L == p->L);
46+
47+
lua_pop(L, 1);
48+
}
49+
50+
lua_pop(L, 1);
51+
assert(lua_gettop(L) == top);
52+
}
53+
#else
54+
# define lcurl__multi_validate_sate(L, p) (void*)(0)
55+
#endif
56+
3157
void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, lua_State *value, int assign_easy){
58+
lcurl__multi_validate_sate(L, p);
59+
3260
if((assign_easy)&&(p->L != value)){
3361
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
3462
lua_pushnil(L);
@@ -145,10 +173,16 @@ static int lcurl_multi_add_handle(lua_State *L){
145173
lua_rawsetp(L, -2, e->curl);
146174
lua_settop(L, 1);
147175

176+
// all `esay` handles have to have same L
177+
lcurl__easy_assign_lua(L, e, p->L, 0);
178+
148179
e->multi = p;
149180

150181
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
151182
code = curl_multi_add_handle(p->curl, e->curl);
183+
#ifndef LCURL_RESET_NULL_LUA
184+
if(curL != NULL)
185+
#endif
152186
lcurl__multi_assign_lua(L, p, curL, 1);
153187

154188
if(code != CURLM_OK){
@@ -166,30 +200,42 @@ static int lcurl_multi_add_handle(lua_State *L){
166200
static int lcurl_multi_remove_handle(lua_State *L){
167201
lcurl_multi_t *p = lcurl_getmulti(L);
168202
lcurl_easy_t *e = lcurl_geteasy_at(L, 2);
203+
CURLMcode code = lcurl__multi_remove_handle(L, p, e);
204+
205+
if(code != CURLM_OK){
206+
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
207+
}
208+
209+
lua_settop(L, 1);
210+
return 1;
211+
}
212+
213+
CURLMcode lcurl__multi_remove_handle(lua_State *L, lcurl_multi_t *p, lcurl_easy_t *e){
169214
CURLMcode code;
170215
lua_State *curL;
171216

172217
if(e->multi != p){
173218
// cURL returns CURLM_OK for such call so we do the same.
174219
// tested on 7.37.1
175-
lua_settop(L, 1);
176-
return 1;
220+
return CURLM_OK;
177221
}
178222

179223
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
180224
code = curl_multi_remove_handle(p->curl, e->curl);
225+
#ifndef LCURL_RESET_NULL_LUA
226+
if(curL != NULL)
227+
#endif
181228
lcurl__multi_assign_lua(L, p, curL, 1);
182229

183-
if(code != CURLM_OK){
184-
lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, code);
230+
if(code == CURLM_OK){
231+
e->multi = NULL;
232+
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
233+
lua_pushnil(L);
234+
lua_rawsetp(L, -2, e->curl);
235+
lua_pop(L, 1);
185236
}
186-
187-
e->multi = NULL;
188-
lua_rawgeti(L, LCURL_LUA_REGISTRY, p->h_ref);
189-
lua_pushnil(L);
190-
lua_rawsetp(L, -2, e->curl);
191-
lua_settop(L, 1);
192-
return 1;
237+
238+
return code;
193239
}
194240

195241
static int lcurl_multi_perform(lua_State *L){
@@ -200,6 +246,9 @@ static int lcurl_multi_perform(lua_State *L){
200246

201247
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
202248
while((code = curl_multi_perform(p->curl, &running_handles)) == CURLM_CALL_MULTI_PERFORM);
249+
#ifndef LCURL_RESET_NULL_LUA
250+
if(curL != NULL)
251+
#endif
203252
lcurl__multi_assign_lua(L, p, curL, 1);
204253

205254
if(code != CURLM_OK){
@@ -232,6 +281,9 @@ static int lcurl_multi_info_read(lua_State *L){
232281

233282
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
234283
code = curl_multi_remove_handle(p->curl, e->curl);
284+
#ifndef LCURL_RESET_NULL_LUA
285+
if(curL != NULL)
286+
#endif
235287
lcurl__multi_assign_lua(L, p, curL, 1);
236288

237289
if(CURLM_OK == code){
@@ -337,6 +389,9 @@ static int lcurl_multi_socket_action(lua_State *L){
337389

338390
curL = p->L; lcurl__multi_assign_lua(L, p, L, 1);
339391
code = curl_multi_socket_action(p->curl, s, mask, &n);
392+
#ifndef LCURL_RESET_NULL_LUA
393+
if(curL != NULL)
394+
#endif
340395
lcurl__multi_assign_lua(L, p, curL, 1);
341396

342397
if(code != CURLM_OK){

src/lcmulti.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@ void lcurl_multi_initlib(lua_State *L, int nup);
3333

3434
void lcurl__multi_assign_lua(lua_State *L, lcurl_multi_t *p, lua_State *value, int assign_easy);
3535

36+
CURLMcode lcurl__multi_remove_handle(lua_State *L, lcurl_multi_t *p, lcurl_easy_t *e);
37+
3638
#endif

0 commit comments

Comments
 (0)