| @@ -25,33 +25,37 @@ |
| |
| #include "urldata.h" |
| #include "api.h" |
| + | #include "curl_threads.h" |
| #include "multiif.h" |
| + | #include "vtls/vtls_scache.h" |
| |
| struct Curl_eapi_fn_props { |
| Curl_eapi_fn fn; |
| uint8_t data_is_killed; /* easy handle is killed in call */ |
| uint8_t recurse; /* may be called when another call is in progress */ |
| uint8_t no_event_cb; /* may not be called during a multi event callback */ |
| + | uint8_t no_scache_lock; /* may not be called with easy's vtls_scache |
| + | locked by current thread */ |
| }; |
| |
| static const struct Curl_eapi_fn_props eapi_fn_props[CURL_EAPI_FN_LAST] = { |
| - | /* function kill rec !ev */ |
| - | { CURL_EAPI_FN_easy_cleanup, 1, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_duphandle, 0, 1, 0 }, |
| - | { CURL_EAPI_FN_easy_getinfo, 0, 1, 0 }, |
| - | { CURL_EAPI_FN_easy_pause, 0, 1, 1 }, |
| - | { CURL_EAPI_FN_easy_perform_ev, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_perform, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_recv, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_reset, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_send, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_setopt, 0, 1, 0 }, |
| - | { CURL_EAPI_FN_easy_ssls_export, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_ssls_import, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_easy_upkeep, 0, 0, 0 }, |
| - | { CURL_EAPI_FN_ws_recv, 0, 1, 0 }, |
| - | { CURL_EAPI_FN_ws_send, 0, 1, 0 }, |
| - | { CURL_EAPI_FN_ws_start_frame, 0, 1, 0 }, |
| + | /* function kill rec !ev !scach */ |
| + | { CURL_EAPI_FN_easy_cleanup, 1, 0, 0, 0 }, |
| + | { CURL_EAPI_FN_easy_duphandle, 0, 1, 0, 0 }, |
| + | { CURL_EAPI_FN_easy_getinfo, 0, 1, 0, 0 }, |
| + | { CURL_EAPI_FN_easy_pause, 0, 1, 1, 0 }, |
| + | { CURL_EAPI_FN_easy_perform_ev, 0, 0, 0, 1 }, |
| + | { CURL_EAPI_FN_easy_perform, 0, 0, 0, 1 }, |
| + | { CURL_EAPI_FN_easy_recv, 0, 0, 0, 1 }, |
| + | { CURL_EAPI_FN_easy_reset, 0, 0, 0, 0 }, |
| + | { CURL_EAPI_FN_easy_send, 0, 0, 0, 1 }, |
| + | { CURL_EAPI_FN_easy_setopt, 0, 1, 0, 0 }, |
| + | { CURL_EAPI_FN_easy_ssls_export, 0, 0, 0, 1 }, |
| + | { CURL_EAPI_FN_easy_ssls_import, 0, 0, 0, 1 }, |
| + | { CURL_EAPI_FN_easy_upkeep, 0, 0, 0, 1 }, |
| + | { CURL_EAPI_FN_ws_recv, 0, 1, 0, 1 }, |
| + | { CURL_EAPI_FN_ws_send, 0, 1, 0, 1 }, |
| + | { CURL_EAPI_FN_ws_start_frame, 0, 1, 0, 0 }, |
| }; |
| |
| struct Curl_mapi_fn_props { |
| @@ -59,29 +63,31 @@ struct Curl_mapi_fn_props { |
| uint8_t multi_is_killed; /* multi handle is killed during call */ |
| uint8_t recurse; /* may be called when another call is in progress */ |
| uint8_t allow_ntfy_cb; /* may be called during a notify callback */ |
| + | uint8_t no_scache_lock; /* may not be called with multi's vtls_scache |
| + | locked by current thread */ |
| }; |
| |
| static const struct Curl_mapi_fn_props mapi_fn_props[CURL_MAPI_FN_LAST] = { |
| - | /* function kill rec ntfy */ |
| - | { CURL_MAPI_FN_multi_add_handle, 0, 0, 1 }, |
| - | { CURL_MAPI_FN_multi_assign, 0, 1, 1 }, |
| - | { CURL_MAPI_FN_multi_cleanup, 1, 0, 0 }, |
| - | { CURL_MAPI_FN_multi_fdset, 0, 0, 1 }, |
| - | { CURL_MAPI_FN_multi_get_handles, 0, 1, 1 }, |
| - | { CURL_MAPI_FN_multi_get_offt, 0, 1, 1 }, |
| - | { CURL_MAPI_FN_multi_info_read, 0, 1, 1 }, |
| - | { CURL_MAPI_FN_multi_notify_disable, 0, 1, 1 }, |
| - | { CURL_MAPI_FN_multi_notify_enable, 0, 1, 1 }, |
| - | { CURL_MAPI_FN_multi_perform, 0, 0, 0 }, |
| - | { CURL_MAPI_FN_multi_poll, 0, 0, 1 }, |
| - | { CURL_MAPI_FN_multi_remove_handle, 0, 0, 1 }, |
| - | { CURL_MAPI_FN_multi_setopt, 0, 0, 1 }, |
| - | { CURL_MAPI_FN_multi_socket_action, 0, 0, 0 }, |
| - | { CURL_MAPI_FN_multi_socket_all, 0, 0, 0 }, |
| - | { CURL_MAPI_FN_multi_socket, 0, 0, 0 }, |
| - | { CURL_MAPI_FN_multi_timeout, 0, 0, 1 }, |
| - | { CURL_MAPI_FN_multi_wait, 0, 0, 1 }, |
| - | { CURL_MAPI_FN_multi_waitfds, 0, 0, 1 }, |
| + | /* function kill rec ntfy !scach */ |
| + | { CURL_MAPI_FN_multi_add_handle, 0, 0, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_assign, 0, 1, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_cleanup, 1, 0, 0, 1 }, |
| + | { CURL_MAPI_FN_multi_fdset, 0, 0, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_get_handles, 0, 1, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_get_offt, 0, 1, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_info_read, 0, 1, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_notify_disable, 0, 1, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_notify_enable, 0, 1, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_perform, 0, 0, 0, 1 }, |
| + | { CURL_MAPI_FN_multi_poll, 0, 0, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_remove_handle, 0, 0, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_setopt, 0, 0, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_socket_action, 0, 0, 0, 1 }, |
| + | { CURL_MAPI_FN_multi_socket_all, 0, 0, 0, 1 }, |
| + | { CURL_MAPI_FN_multi_socket, 0, 0, 0, 1 }, |
| + | { CURL_MAPI_FN_multi_timeout, 0, 0, 1, 1 }, |
| + | { CURL_MAPI_FN_multi_wait, 0, 0, 1, 0 }, |
| + | { CURL_MAPI_FN_multi_waitfds, 0, 0, 1, 0 }, |
| }; |
| |
| struct Curl_cbapi_fn_props { |
| @@ -248,6 +254,19 @@ bool Curl_eapi_enter(struct Curl_eapi_guard *guard, |
| goto out; |
| } |
| |
| + | #if defined(USE_SSL) && defined(USE_MUTEX) |
| + | if(fn_props->no_scache_lock && |
| + | Curl_ssl_scache_is_locked_by_current_thread(data)) { |
| + | #ifdef CURLVERBOSE |
| + | DEBUGF(curl_mfprintf(stderr, |
| + | "EAPI guard: calling %u while vtls_scache is locked by " |
| + | "current thread\n", (uint16_t)fn)); |
| + | #endif |
| + | result = CURLE_RECURSIVE_API_CALL; |
| + | goto out; |
| + | } |
| + | #endif |
| + | |
| /* all fine, add to data's callstack */ |
| if(data->callstack.count >= CURL_EAPI_MAX_RECURSION) { |
| result = CURLE_RECURSIVE_API_CALL; |
| @@ -318,6 +337,19 @@ bool Curl_mapi_enter(struct Curl_mapi_guard *guard, |
| goto out; |
| } |
| |
| + | #if defined(USE_SSL) && defined(USE_MUTEX) |
| + | if(fn_props->no_scache_lock && multi->ssl_scache && |
| + | Curl_ssl_scache_is_locked_by_current_thread(multi->admin)) { |
| + | #ifdef CURLVERBOSE |
| + | DEBUGF(curl_mfprintf(stderr, |
| + | "MAPI guard: calling %u while its vtls_scache is locked by " |
| + | "current thread\n", (uint16_t)fn)); |
| + | #endif |
| + | mresult = CURLM_RECURSIVE_API_CALL; |
| + | goto out; |
| + | } |
| + | #endif |
| + | |
| /* all fine, add to data's callstack */ |
| if(multi->callstack.count >= CURL_MAPI_MAX_RECURSION) { |
| mresult = CURLM_RECURSIVE_API_CALL; |