#endif /* HAVE_GETADDRINFO */
-#ifdef ENABLE_WAKEUP
+#ifdef ENABLE_INTERNAL_WAKEUP
static void async_thrdd_event(const struct curl_thrdq *tqueue,
Curl_thrdq_event ev,
void *user_data)
(void)tqueue;
switch(ev) {
case CURL_THRDQ_EV_ITEM_DONE:
- (void)curl_multi_wakeup(multi);
+ Curl_multi_wakeup_internal(multi);
break;
default:
break;
#endif
if(!async->done) {
-#ifndef ENABLE_WAKEUP
+#ifndef ENABLE_INTERNAL_WAKEUP
timediff_t stutter_ms, elapsed_ms;
elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &async->start);
if(elapsed_ms < 3)
if(thrdd->rr.channel)
(void)Curl_ares_perform(thrdd->rr.channel, 0);
#endif
-#ifndef ENABLE_WAKEUP
+#ifndef ENABLE_INTERNAL_WAKEUP
Curl_async_thrdd_multi_process(data->multi);
#endif
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
#endif
+#ifdef ENABLE_INTERNAL_WAKEUP
+ multi->wakeup_internal[0] = CURL_SOCKET_BAD;
+ multi->wakeup_internal[1] = CURL_SOCKET_BAD;
+#endif
if(Curl_mntfy_resize(multi) ||
Curl_uint32_bset_resize(&multi->process, xfer_table_size) ||
if(Curl_wakeup_init(multi->wakeup_pair, TRUE) < 0)
goto error;
#endif
+#ifdef ENABLE_INTERNAL_WAKEUP
+ if(Curl_wakeup_init(multi->wakeup_internal, TRUE) < 0)
+ goto error;
+#endif
if(Curl_probeipv6(multi))
goto error;
#ifdef ENABLE_WAKEUP
Curl_wakeup_destroy(multi->wakeup_pair);
#endif
+#ifdef ENABLE_INTERNAL_WAKEUP
+ Curl_wakeup_destroy(multi->wakeup_internal);
+#endif
curlx_free(multi);
return NULL;
static CURLMcode multi_assess_wakeup(struct Curl_multi *multi)
{
-#ifdef ENABLE_WAKEUP
+#ifdef ENABLE_INTERNAL_WAKEUP
if(multi->socket_cb)
return Curl_multi_ev_assess_xfer(multi, multi->admin);
#else
CURLcode result = CURLE_OK;
Curl_pollset_reset(ps);
-#ifdef ENABLE_WAKEUP
+#ifdef ENABLE_INTERNAL_WAKEUP
/* The admin handle always listens on the wakeup socket when there
* are transfers alive. */
if(data->multi && (data == data->multi->admin) &&
data->multi->xfers_really_alive) {
CURL_TRC_M(data, "adding wakeup, %u xfers really alive",
data->multi->xfers_really_alive);
- result = Curl_pollset_add_in(data, ps, data->multi->wakeup_pair[0]);
+ result = Curl_pollset_add_in(data, ps, data->multi->wakeup_internal[0]);
}
#endif
/* If the transfer has no connection, this is fine. Happens when
return mresult;
}
+#ifdef ENABLE_INTERNAL_WAKEUP
+void Curl_multi_wakeup_internal(struct Curl_multi *multi)
+{
+ /* This is expected to be invocable from another thread which
+ * does NOT outlive the multi handle. Check for sanity. */
+ if(GOOD_MULTI_HANDLE(multi))
+ Curl_wakeup_signal(multi->wakeup_internal);
+ else
+ DEBUGASSERT(0);
+}
+#endif
+
/*
* multi_ischanged() is called
*
Curl_uint32_bset_remove(&multi->dirty, data->mid);
if(data == multi->admin) {
-#ifdef ENABLE_WAKEUP
+#ifdef ENABLE_INTERNAL_WAKEUP
/* Consume any pending wakeup signals before processing.
* This is necessary for event based processing. See #21547 */
- (void)Curl_wakeup_consume(multi->wakeup_pair, TRUE);
+ (void)Curl_wakeup_consume(multi->wakeup_internal, TRUE);
#endif
#ifdef USE_RESOLV_THREADED
Curl_async_thrdd_multi_process(multi);
#ifdef ENABLE_WAKEUP
Curl_wakeup_destroy(multi->wakeup_pair);
#endif
+#ifdef ENABLE_INTERNAL_WAKEUP
+ Curl_wakeup_destroy(multi->wakeup_internal);
+#endif
multi_xfer_bufs_free(multi);
Curl_mntfy_cleanup(multi);
#if !defined(CURL_DISABLE_SOCKETPAIR) && !defined(USE_WINSOCK)
#define ENABLE_WAKEUP
#endif
+#if !defined(CURL_DISABLE_SOCKETPAIR) && \
+ defined(USE_RESOLV_THREADED) && \
+ !defined(USE_WINSOCK)
+#define ENABLE_INTERNAL_WAKEUP
+#endif
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
#ifdef ENABLE_WAKEUP
curl_socket_t wakeup_pair[2]; /* eventfd()/pipe()/socketpair() used for
wakeup 0 is used for read, 1 is used
- for write */
+ for write. Used by curl_multi_wakeup() */
+#endif
+#ifdef ENABLE_INTERNAL_WAKEUP
+ curl_socket_t wakeup_internal[2]; /* eventfd()/pipe()/socketpair() used for
+ wakeup 0 is used for read, 1 is used
+ for write. Used for internal wakeups,
+ e.g. threaded resolver. */
#endif
unsigned int max_concurrent_streams;
unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of
void Curl_multi_set_now(struct Curl_multi *multi);
+#ifdef ENABLE_INTERNAL_WAKEUP
+void Curl_multi_wakeup_internal(struct Curl_multi *multi);
+#endif
+
#endif /* HEADER_CURL_MULTIIF_H */
test2309 test2310 test2311 \
\
test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 \
-test2408 test2409 test2410 test2411 test2412 test2413 \
+test2408 test2409 test2410 test2411 test2412 test2413 test2414 \
\
test2500 test2501 test2502 test2503 test2504 test2505 test2506 \
\
--- /dev/null
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+multi
+wakeup
+</keywords>
+</info>
+
+# Client-side
+<client>
+<features>
+wakeup
+</features>
+<server>
+</server>
+<tool>
+lib%TESTNUMBER
+</tool>
+<name>
+wakeup, perform and poll needs to exit
+</name>
+<command>
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+</verify>
+</testcase>
lib2023.c lib2032.c lib2082.c \
lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c \
lib2402.c lib2404.c lib2405.c \
- lib2412.c \
+ lib2412.c lib2414.c \
lib2502.c lib2504.c lib2505.c lib2506.c \
lib2700.c \
lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c \
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Dmitry Karpov <dkarpov1970@gmail.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "first.h"
+#include "testtrace.h"
+
+static CURLcode test_lib2414(const char *URL)
+{
+ CURLM *multi = NULL;
+ CURLcode result = CURLE_OK;
+ int running;
+
+ (void)URL;
+ global_init(CURL_GLOBAL_ALL);
+
+ multi = curl_multi_init();
+ if(!multi) {
+ curl_mfprintf(stderr, "curl_multi_init() failed\n");
+ result = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+
+ curl_multi_wakeup(multi);
+ curl_multi_perform(multi, &running);
+ curl_multi_poll(multi, NULL, 0, INT_MAX, NULL);
+
+test_cleanup:
+ if(multi)
+ curl_multi_cleanup(multi);
+ curl_global_cleanup();
+ return result;
+}