@@ -28,6 +28,31 @@ static const char *LCURL_EASY = LCURL_EASY_NAME;
2828# define LCURL_E_UNKNOWN_OPTION CURLE_UNKNOWN_TELNET_OPTION
2929#endif
3030
31+ /* Before call curl_XXX function which can call any callback
32+ * need set Curren Lua thread pointer in easy/multi contexts.
33+ * But it also possible that we already in callback call.
34+ * E.g. `curl_easy_pause` function may be called from write callback.
35+ * and it even may be called in different thread.
36+ * ```Lua
37+ * multi:add_handle(easy)
38+ * easy:setopt_writefunction(function(...)
39+ * coroutine.wrap(function() multi:add_handle(easy2) end)()
40+ * end)
41+ * ```
42+ * So we have to restore previews Lua state in callback contexts.
43+ */
44+ void lcurl__easy_assign_lua (lua_State * L , lcurl_easy_t * p , lua_State * value , int assign_multi ){
45+ if (p -> multi && assign_multi ){
46+ lcurl__multi_assign_lua (L , p -> multi , value , 1 );
47+ }
48+ else {
49+ p -> L = value ;
50+ if (p -> post ){
51+ p -> post -> L = value ;
52+ }
53+ }
54+ }
55+
3156//{
3257
3358int lcurl_easy_create (lua_State * L , int error_mode ){
@@ -72,24 +97,25 @@ lcurl_easy_t *lcurl_geteasy_at(lua_State *L, int i){
7297 return p ;
7398}
7499
100+ static int lcurl_easy_to_s (lua_State * L ){
101+ lcurl_easy_t * p = (lcurl_easy_t * )lutil_checkudatap (L , 1 , LCURL_EASY );
102+ lua_pushfstring (L , LCURL_PREFIX " Easy (%p)" , (void * )p );
103+ return 1 ;
104+ }
105+
75106static int lcurl_easy_cleanup (lua_State * L ){
76107 lcurl_easy_t * p = lcurl_geteasy (L );
77108 int i ;
78109
79110 if (p -> curl ){
80- p -> L = L ;
81- if (p -> post ){
82- p -> post -> L = L ;
83- }
111+ lua_State * curL ;
112+
84113 // In my tests when I cleanup some easy handle.
85114 // timerfunction called only for single multi handle.
86- if (p -> multi ){
87- p -> multi -> L = L ;
88- }
115+ curL = p -> L ; lcurl__easy_assign_lua (L , p , L , 1 );
89116 curl_easy_cleanup (p -> curl );
90- if (p -> multi ){
91- p -> multi -> L = NULL ;
92- }
117+ lcurl__easy_assign_lua (L , p , curL , 1 );
118+
93119 p -> curl = NULL ;
94120 }
95121
@@ -127,18 +153,17 @@ static int lcurl_easy_cleanup(lua_State *L){
127153static int lcurl_easy_perform (lua_State * L ){
128154 lcurl_easy_t * p = lcurl_geteasy (L );
129155 CURLcode code ;
156+ lua_State * curL ;
130157 int top = 1 ;
131158 lua_settop (L , top );
132159
133160 assert (p -> rbuffer .ref == LUA_NOREF );
134161
135162 // store reference to current coroutine to callbacks
136- p -> L = L ;
137- if (p -> post ){
138- p -> post -> L = L ;
139- }
140-
163+ // User should not call `perform` if handle assign to multi
164+ curL = p -> L ; lcurl__easy_assign_lua (L , p , L , 0 );
141165 code = curl_easy_perform (p -> curl );
166+ lcurl__easy_assign_lua (L , p , curL , 0 );
142167
143168 if (p -> rbuffer .ref != LUA_NOREF ){
144169 luaL_unref (L , LCURL_LUA_REGISTRY , p -> rbuffer .ref );
@@ -744,6 +769,7 @@ static size_t lcurl_write_callback_(lua_State*L,
744769
745770static size_t lcurl_write_callback (char * ptr , size_t size , size_t nmemb , void * arg ){
746771 lcurl_easy_t * p = arg ;
772+ assert (NULL != p -> L );
747773 return lcurl_write_callback_ (p -> L , p , & p -> wr , ptr , size , nmemb );
748774}
749775
@@ -847,11 +873,13 @@ static size_t lcurl_easy_read_callback(char *buffer, size_t size, size_t nitems,
847873 if (p -> magic == LCURL_HPOST_STREAM_MAGIC ){
848874 return lcurl_hpost_read_callback (buffer , size , nitems , arg );
849875 }
876+ assert (NULL != p -> L );
850877 return lcurl_read_callback (p -> L , & p -> rd , & p -> rbuffer , buffer , size , nitems );
851878}
852879
853880static size_t lcurl_hpost_read_callback (char * buffer , size_t size , size_t nitems , void * arg ){
854881 lcurl_hpost_stream_t * p = arg ;
882+ assert (NULL != p -> L );
855883 return lcurl_read_callback (* p -> L , & p -> rd , & p -> rbuffer , buffer , size , nitems );
856884}
857885
@@ -869,6 +897,7 @@ static int lcurl_easy_set_READFUNCTION(lua_State *L){
869897
870898static size_t lcurl_header_callback (char * ptr , size_t size , size_t nmemb , void * arg ){
871899 lcurl_easy_t * p = arg ;
900+ assert (NULL != p -> L );
872901 return lcurl_write_callback_ (p -> L , p , & p -> hd , ptr , size , nmemb );
873902}
874903
@@ -889,10 +918,12 @@ static int lcurl_xferinfo_callback(void *arg, curl_off_t dltotal, curl_off_t dln
889918{
890919 lcurl_easy_t * p = arg ;
891920 lua_State * L = p -> L ;
921+ int n , top , ret = 0 ;
922+
923+ assert (NULL != p -> L );
892924
893- int ret = 0 ;
894- int top = lua_gettop (L );
895- int n = lcurl_util_push_cb (L , & p -> pr );
925+ top = lua_gettop (L );
926+ n = lcurl_util_push_cb (L , & p -> pr );
896927
897928 lua_pushnumber ( L , (lua_Number )dltotal );
898929 lua_pushnumber ( L , (lua_Number )dlnow );
@@ -1033,8 +1064,14 @@ static int lcurl_easy_getinfo(lua_State *L){
10331064
10341065static int lcurl_easy_pause (lua_State * L ){
10351066 lcurl_easy_t * p = lcurl_geteasy (L );
1067+ lua_State * curL ;
10361068 int mask = luaL_checkint (L , 2 );
1037- CURLcode code = curl_easy_pause (p -> curl , mask );
1069+ CURLcode code ;
1070+
1071+ curL = p -> L ; lcurl__easy_assign_lua (L , p , L , 1 );
1072+ code = curl_easy_pause (p -> curl , mask );
1073+ lcurl__easy_assign_lua (L , p , curL , 1 );
1074+
10381075 if (code != CURLE_OK ){
10391076 return lcurl_fail_ex (L , p -> err_mode , LCURL_ERROR_EASY , code );
10401077 }
@@ -1096,19 +1133,20 @@ static const struct luaL_Reg lcurl_easy_methods[] = {
10961133 #include "lcinfoeasy.h"
10971134#undef OPT_ENTRY
10981135
1099- { "pause" , lcurl_easy_pause },
1100- { "reset" , lcurl_easy_reset },
1101- { "setopt" , lcurl_easy_setopt },
1102- { "getinfo" , lcurl_easy_getinfo },
1103- { "unsetopt" , lcurl_easy_unsetopt },
1104- { "escape" , lcurl_easy_escape },
1105- { "unescape" , lcurl_easy_unescape },
1106- { "perform" , lcurl_easy_perform },
1107- { "close" , lcurl_easy_cleanup },
1108- { "__gc" , lcurl_easy_cleanup },
1109-
1110- { "setdata" , lcurl_easy_setdata },
1111- { "getdata" , lcurl_easy_getdata },
1136+ { "pause" , lcurl_easy_pause },
1137+ { "reset" , lcurl_easy_reset },
1138+ { "setopt" , lcurl_easy_setopt },
1139+ { "getinfo" , lcurl_easy_getinfo },
1140+ { "unsetopt" , lcurl_easy_unsetopt },
1141+ { "escape" , lcurl_easy_escape },
1142+ { "unescape" , lcurl_easy_unescape },
1143+ { "perform" , lcurl_easy_perform },
1144+ { "close" , lcurl_easy_cleanup },
1145+ { "__gc" , lcurl_easy_cleanup },
1146+ { "__tostring" , lcurl_easy_to_s },
1147+
1148+ { "setdata" , lcurl_easy_setdata },
1149+ { "getdata" , lcurl_easy_getdata },
11121150
11131151 {NULL ,NULL }
11141152};
0 commit comments