← Commit list

04692d3bae

Stefan Eissing
Stefan Eissing
2026-09-07
SUCCESS Duration: 397s

Subject

cshutdown: make it smaller

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/conncache.c+25 -15
@@ -182,7 +182,6 @@ static void cpool_discard_conn(struct cpool *cpool,
struct connectdata *conn,
bool aborted)
{
- struct cshutdn *cshutdn;
struct Curl_easy *admin;
bool done = FALSE;
@@ -221,11 +220,19 @@ static void cpool_discard_conn(struct cpool *cpool,
Curl_conn_shutdown_once(admin, conn, &done);
}
- cshutdn = Curl_cshutdn_get(data);
- if(done || !cshutdn)
+ if(done || !data->multi)
Curl_conn_terminate(admin, conn, FALSE);
- else
- Curl_cshutdn_add(cshutdn, conn, cpool->num_conn);
+ else {
+ struct Curl_multi *multi = data->multi;
+ size_t max_shutdowns = multi->max_total_connections;
+ if(cpool->num_conn < max_shutdowns)
+ max_shutdowns -= cpool->num_conn;
+ else if(max_shutdowns)
+ max_shutdowns = 1;
+ else /* no connection limit set, let's restrict growth nevertheless */
+ max_shutdowns = CURLMAX(cpool->num_conn / 4, 128);
+ Curl_cshutdn_add(&multi->cshutdn, multi, conn, max_shutdowns);
+ }
}
void Curl_cpool_destroy(struct cpool *cpool, struct Curl_easy *admin)
@@ -454,7 +461,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
const struct curltime *pnow)
{
struct cpool *cpool = cpool_get_instance(data);
- struct cshutdn *cshutdn = Curl_cshutdn_get(data);
+ struct Curl_multi *multi = data->multi;
struct Curl_easy *admin;
struct cpool_bundle *bundle;
size_t dest_limit = 0;
@@ -466,9 +473,9 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
return CPOOL_LIMIT_OK;
/* multi determines the limits, no matter who owns the pool */
- if(data->multi) {
- dest_limit = data->multi->max_host_connections;
- total_limit = data->multi->max_total_connections;
+ if(multi) {
+ dest_limit = multi->max_host_connections;
+ total_limit = multi->max_total_connections;
}
if(!dest_limit && !total_limit)
@@ -481,11 +488,13 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
bundle = cpool_find_bundle(cpool, conn);
live = bundle ? Curl_llist_count(&bundle->conns) : 0;
- shutdowns = Curl_cshutdn_dest_count(cshutdn, conn->destination);
+ shutdowns =
+ multi ? Curl_cshutdn_dest_count(&multi->cshutdn, conn->destination) : 0;
while((live + shutdowns) >= dest_limit) {
if(shutdowns) {
/* close one connection in shutdown right away, if we can */
- if(!Curl_cshutdn_close_oldest(cshutdn, conn->destination))
+ if(!Curl_cshutdn_close_oldest(&multi->cshutdn, multi->admin,
+ conn->destination))
break;
}
else if(!bundle)
@@ -508,7 +517,8 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
bundle = cpool_find_bundle(cpool, conn);
live = bundle ? Curl_llist_count(&bundle->conns) : 0;
}
- shutdowns = Curl_cshutdn_dest_count(cshutdn, conn->destination);
+ shutdowns = multi ?
+ Curl_cshutdn_dest_count(&multi->cshutdn, conn->destination) : 0;
}
if((live + shutdowns) >= dest_limit) {
res = CPOOL_LIMIT_DEST;
@@ -517,11 +527,11 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
}
if(total_limit) {
- shutdowns = Curl_cshutdn_count(cshutdn);
+ shutdowns = multi ? Curl_cshutdn_count(&multi->cshutdn) : 0;
while((cpool->num_conn + shutdowns) >= total_limit) {
if(shutdowns) {
/* close one connection in shutdown right away, if we can */
- if(!Curl_cshutdn_close_oldest(cshutdn, NULL))
+ if(!Curl_cshutdn_close_oldest(&multi->cshutdn, multi->admin, NULL))
break;
}
else {
@@ -536,7 +546,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
oldest_idle->connection_id, cpool->num_conn, total_limit);
cpool_evict_conn(cpool, admin, oldest_idle);
}
- shutdowns = Curl_cshutdn_count(cshutdn);
+ shutdowns = multi ? Curl_cshutdn_count(&multi->cshutdn) : 0;
}
if((cpool->num_conn + shutdowns) >= total_limit) {
res = CPOOL_LIMIT_TOTAL;
lib/cshutdn.c+34 -50
@@ -38,13 +38,6 @@
#include "curlx/strparse.h"
-struct cshutdn *Curl_cshutdn_get(struct Curl_easy *data)
-{
- if(data && data->multi)
- return &data->multi->cshutdn;
- return NULL;
-}
-
static void cshutdn_run_conn_handler(struct Curl_easy *data,
struct connectdata *conn)
{
@@ -166,6 +159,7 @@ void Curl_conn_terminate(struct Curl_easy *admin,
}
static bool cshutdn_destroy_oldest(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
const char *destination)
{
struct Curl_llist_node *e;
@@ -184,8 +178,8 @@ static bool cshutdn_destroy_oldest(struct cshutdn *cshutdn,
conn = Curl_node_elem(e);
Curl_node_remove(e);
sigpipe_init(&sigpipe_ctx);
- sigpipe_apply(cshutdn->multi->admin, &sigpipe_ctx);
- Curl_conn_terminate(cshutdn->multi->admin, conn, FALSE);
+ sigpipe_apply(admin, &sigpipe_ctx);
+ Curl_conn_terminate(admin, conn, FALSE);
sigpipe_restore(&sigpipe_ctx);
return TRUE;
}
@@ -193,10 +187,11 @@ static bool cshutdn_destroy_oldest(struct cshutdn *cshutdn,
}
bool Curl_cshutdn_close_oldest(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
const char *destination)
{
if(cshutdn) {
- return cshutdn_destroy_oldest(cshutdn, destination);
+ return cshutdn_destroy_oldest(cshutdn, admin, destination);
}
return FALSE;
}
@@ -204,6 +199,7 @@ bool Curl_cshutdn_close_oldest(struct cshutdn *cshutdn,
#define NUM_POLLS_ON_STACK 10
static CURLcode cshutdn_wait(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
int timeout_ms)
{
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
@@ -212,7 +208,7 @@ static CURLcode cshutdn_wait(struct cshutdn *cshutdn,
Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK);
- result = Curl_cshutdn_add_pollfds(cshutdn, &cpfds);
+ result = Curl_cshutdn_add_pollfds(cshutdn, admin, &cpfds);
if(result)
goto out;
@@ -224,11 +220,11 @@ out:
}
static void cshutdn_perform(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
struct Curl_sigpipe_ctx *sigpipe_ctx)
{
struct Curl_llist_node *e = Curl_llist_head(&cshutdn->list);
struct Curl_llist_node *enext;
- struct Curl_easy *admin = cshutdn->multi->admin;
struct connectdata *conn;
timediff_t next_expire_ms = 0, ms;
bool done;
@@ -262,9 +258,9 @@ static void cshutdn_perform(struct cshutdn *cshutdn,
}
static void cshutdn_terminate_all(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
int timeout_ms)
{
- struct Curl_easy *admin = cshutdn->multi->admin;
struct curltime started = *Curl_pgrs_now(admin);
struct Curl_llist_node *e;
struct Curl_sigpipe_ctx sigpipe_ctx;
@@ -276,7 +272,7 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
timediff_t spent_ms;
int remain_ms;
- cshutdn_perform(cshutdn, &sigpipe_ctx);
+ cshutdn_perform(cshutdn, admin, &sigpipe_ctx);
if(!Curl_llist_head(&cshutdn->list)) {
CURL_TRC_M(admin, "[SHUTDOWN] shutdown finished cleanly");
@@ -292,7 +288,7 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
}
remain_ms = timeout_ms - (int)spent_ms;
- if(cshutdn_wait(cshutdn, remain_ms)) {
+ if(cshutdn_wait(cshutdn, admin, remain_ms)) {
CURL_TRC_M(admin, "[SHUTDOWN] shutdown finished, aborted");
break;
}
@@ -311,24 +307,18 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
sigpipe_restore(&sigpipe_ctx);
}
-int Curl_cshutdn_init(struct cshutdn *cshutdn,
- struct Curl_multi *multi)
+void Curl_cshutdn_init(struct cshutdn *cshutdn)
{
- DEBUGASSERT(multi);
- cshutdn->multi = multi;
Curl_llist_init(&cshutdn->list, NULL);
- cshutdn->initialized = TRUE;
- return 0; /* good */
}
void Curl_cshutdn_destroy(struct cshutdn *cshutdn,
struct Curl_easy *admin)
{
- if(cshutdn->initialized && admin) {
+ if(admin) {
int timeout_ms = 0;
/* for testing, run graceful shutdown */
#ifdef DEBUGBUILD
- DEBUGASSERT(!admin->mid);
{
const char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
if(p) {
@@ -338,13 +328,12 @@ void Curl_cshutdn_destroy(struct cshutdn *cshutdn,
}
}
#endif
-
- CURL_TRC_M(admin, "[SHUTDOWN] destroy, %zu connections, timeout=%dms",
- Curl_llist_count(&cshutdn->list), timeout_ms);
- cshutdn_terminate_all(cshutdn, timeout_ms);
+ if(Curl_llist_count(&cshutdn->list)) {
+ CURL_TRC_M(admin, "[SHUTDOWN] destroy, %zu connections, timeout=%dms",
+ Curl_llist_count(&cshutdn->list), timeout_ms);
+ cshutdn_terminate_all(cshutdn, admin, timeout_ms);
+ }
}
- cshutdn->multi = NULL;
- cshutdn->initialized = FALSE;
}
size_t Curl_cshutdn_count(struct cshutdn *cshutdn)
@@ -372,38 +361,32 @@ size_t Curl_cshutdn_dest_count(struct cshutdn *cshutdn,
return 0;
}
-static CURLMcode cshutdn_update_ev(struct cshutdn *cshutdn,
+static CURLMcode cshutdn_update_ev(struct Curl_multi *multi,
struct connectdata *conn)
{
- struct Curl_easy *admin = cshutdn->multi->admin;
CURLMcode mresult;
-
- DEBUGASSERT(cshutdn);
- DEBUGASSERT(cshutdn->multi->socket_cb);
-
- Curl_attach_connection(admin, conn, FALSE);
- mresult = Curl_multi_ev_assess_conn(cshutdn->multi, admin, conn);
- Curl_detach_connection(admin);
+ Curl_attach_connection(multi->admin, conn, FALSE);
+ mresult = Curl_multi_ev_assess_conn(multi, multi->admin, conn);
+ Curl_detach_connection(multi->admin);
return mresult;
}
void Curl_cshutdn_add(struct cshutdn *cshutdn,
+ struct Curl_multi *multi,
struct connectdata *conn,
- size_t conns_in_pool)
+ size_t max_shutdowns)
{
- struct Curl_easy *admin = cshutdn->multi->admin;
- size_t max_total = cshutdn->multi->max_total_connections;
+ struct Curl_easy *admin = multi->admin;
/* Add the connection to our shutdown list for non-blocking shutdown
* during multi processing. */
- if(max_total > 0 &&
- (max_total <= (conns_in_pool + Curl_llist_count(&cshutdn->list)))) {
+ if(max_shutdowns <= Curl_llist_count(&cshutdn->list)) {
CURL_TRC_M(admin, "[SHUTDOWN] discarding oldest shutdown connection "
- "due to connection limit of %zu", max_total);
- cshutdn_destroy_oldest(cshutdn, NULL);
+ "due to shutdown limit of %zu", max_shutdowns);
+ cshutdn_destroy_oldest(cshutdn, admin, NULL);
}
- if(cshutdn->multi->socket_cb && cshutdn_update_ev(cshutdn, conn)) {
+ if(multi->socket_cb && cshutdn_update_ev(multi, conn)) {
CURL_TRC_M(admin, "[SHUTDOWN] update events failed, discarding #%"
FMT_OFF_T, conn->connection_id);
Curl_conn_terminate(admin, conn, FALSE);
@@ -417,18 +400,19 @@ void Curl_cshutdn_add(struct cshutdn *cshutdn,
}
void Curl_cshutdn_perform(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
struct Curl_sigpipe_ctx *sigpipe_ctx)
{
- cshutdn_perform(cshutdn, sigpipe_ctx);
+ cshutdn_perform(cshutdn, admin, sigpipe_ctx);
}
/* return fd_set info about the shutdown connections */
void Curl_cshutdn_setfds(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
fd_set *read_fd_set, fd_set *write_fd_set,
int *maxfd)
{
if(Curl_llist_head(&cshutdn->list)) {
- struct Curl_easy *admin = cshutdn->multi->admin;
struct Curl_llist_node *e;
struct easy_pollset ps;
@@ -465,13 +449,13 @@ void Curl_cshutdn_setfds(struct cshutdn *cshutdn,
/* return information about the shutdown connections */
unsigned int Curl_cshutdn_add_waitfds(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
struct Curl_waitfds *cwfds)
{
unsigned int need = 0;
if(Curl_llist_head(&cshutdn->list)) {
struct Curl_llist_node *e;
- struct Curl_easy *admin = cshutdn->multi->admin;
struct easy_pollset ps;
struct connectdata *conn;
CURLcode result;
@@ -493,6 +477,7 @@ unsigned int Curl_cshutdn_add_waitfds(struct cshutdn *cshutdn,
}
CURLcode Curl_cshutdn_add_pollfds(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
struct curl_pollfds *cpfds)
{
CURLcode result = CURLE_OK;
@@ -500,7 +485,6 @@ CURLcode Curl_cshutdn_add_pollfds(struct cshutdn *cshutdn,
if(Curl_llist_head(&cshutdn->list)) {
struct Curl_llist_node *e;
struct easy_pollset ps;
- struct Curl_easy *admin = cshutdn->multi->admin;
struct connectdata *conn;
Curl_pollset_init(&ps);
lib/cshutdn.h+9 -9
@@ -53,16 +53,10 @@ void Curl_conn_terminate(struct Curl_easy *admin,
* sockets to monitor via the multi handle. */
struct cshutdn {
struct Curl_llist list; /* connections being shut down */
- struct Curl_multi *multi; /* the multi owning this */
- BIT(initialized);
};
-/* Get the cshutdn instance relevant for `data` or NULL if there is none */
-struct cshutdn *Curl_cshutdn_get(struct Curl_easy *data);
-
/* Init as part of the given multi handle. */
-int Curl_cshutdn_init(struct cshutdn *cshutdn,
- struct Curl_multi *multi);
+void Curl_cshutdn_init(struct cshutdn *cshutdn);
/* Terminate all remaining connections and free resources. */
void Curl_cshutdn_destroy(struct cshutdn *cshutdn,
@@ -79,27 +73,33 @@ size_t Curl_cshutdn_dest_count(struct cshutdn *cshutdn,
* when destination is NULL for any destination.
* Return TRUE if a connection has been closed. */
bool Curl_cshutdn_close_oldest(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
const char *destination);
/* Add a connection to have it shut down. Terminate the oldest
- * connection when total connection limit of multi is being reached. */
+ * connection when shutdowns exceed max_shutdowns. */
void Curl_cshutdn_add(struct cshutdn *cshutdn,
+ struct Curl_multi *multi,
struct connectdata *conn,
- size_t conns_in_pool);
+ size_t max_shutdowns);
/* Add sockets and POLLIN/OUT flags for connections being shut down. */
CURLcode Curl_cshutdn_add_pollfds(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
struct curl_pollfds *cpfds);
unsigned int Curl_cshutdn_add_waitfds(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
struct Curl_waitfds *cwfds);
void Curl_cshutdn_setfds(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
fd_set *read_fd_set, fd_set *write_fd_set,
int *maxfd);
/* Run maintenance on all connections. */
void Curl_cshutdn_perform(struct cshutdn *cshutdn,
+ struct Curl_easy *admin,
struct Curl_sigpipe_ctx *sigpipe_ctx);
#endif /* HEADER_CURL_CSHUTDN_H */
lib/multi.c+6 -8
@@ -260,6 +260,7 @@ struct Curl_multi *Curl_multi_handle(uint32_t xfer_table_size,
Curl_uint32_bset_init(&multi->pending);
Curl_uint32_bset_init(&multi->msgsent);
Curl_hash_init(&multi->proto_hash, 23, CURL_HASH_TYPE_BYTES, ph_freeentry);
+ Curl_cshutdn_init(&multi->cshutdn);
multi->multiplexing = TRUE;
multi->max_concurrent_streams = 100;
@@ -286,9 +287,6 @@ struct Curl_multi *Curl_multi_handle(uint32_t xfer_table_size,
Curl_uint32_tbl_add(&multi->xfers, multi->admin, &multi->admin->mid);
Curl_uint32_bset_add(&multi->process, multi->admin->mid);
- if(Curl_cshutdn_init(&multi->cshutdn, multi))
- goto error;
-
Curl_cpool_init(&multi->cpool, NULL, chashsize);
#ifdef USE_SSL
@@ -1279,8 +1277,8 @@ CURLMcode curl_multi_fdset(CURLM *m,
} while(Curl_uint32_bset_next(&multi->process, mid, &mid));
}
- Curl_cshutdn_setfds(&multi->cshutdn, read_fd_set, write_fd_set,
- &this_max_fd);
+ Curl_cshutdn_setfds(&multi->cshutdn, multi->admin,
+ read_fd_set, write_fd_set, &this_max_fd);
*max_fd = this_max_fd;
Curl_pollset_cleanup(&ps);
@@ -1328,7 +1326,7 @@ CURLMcode curl_multi_waitfds(CURLM *m,
} while(Curl_uint32_bset_next(&multi->process, mid, &mid));
}
- need += Curl_cshutdn_add_waitfds(&multi->cshutdn, &cwfds);
+ need += Curl_cshutdn_add_waitfds(&multi->cshutdn, multi->admin, &cwfds);
if(need != cwfds.n && ufds)
mresult = CURLM_OUT_OF_MEMORY;
@@ -1563,7 +1561,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
} while(Curl_uint32_bset_next(&multi->process, mid, &mid));
}
- if(Curl_cshutdn_add_pollfds(&multi->cshutdn, &cpfds)) {
+ if(Curl_cshutdn_add_pollfds(&multi->cshutdn, multi->admin, &cpfds)) {
mresult = CURLM_OUT_OF_MEMORY;
goto out;
}
@@ -2741,7 +2739,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
#ifdef USE_RESOLV_THREADED
Curl_async_thrdd_multi_process(multi);
#endif
- Curl_cshutdn_perform(&multi->cshutdn, sigpipe_ctx);
+ Curl_cshutdn_perform(&multi->cshutdn, multi->admin, sigpipe_ctx);
goto out;
}