Merge branch 'initiate-cancel'

Allow proper shutdown if a deadlock is caused by too many concurrent
blocking initiation requests.

References strongswan/strongswan#2776
This commit is contained in:
Tobias Brunner 2025-05-19 17:21:57 +02:00
commit 688b9e27d5
2 changed files with 24 additions and 12 deletions

View File

@ -400,6 +400,8 @@ METHOD(job_t, destroy_job, void,
{ {
this->listener.lock->destroy(this->listener.lock); this->listener.lock->destroy(this->listener.lock);
DESTROY_IF(this->listener.done); DESTROY_IF(this->listener.done);
DESTROY_IF(this->listener.child_cfg);
DESTROY_IF(this->listener.peer_cfg);
free(this); free(this);
} }
} }
@ -416,14 +418,11 @@ METHOD(job_t, initiate_execute, job_requeue_t,
{ {
ike_sa_t *ike_sa; ike_sa_t *ike_sa;
interface_listener_t *listener = &job->listener; interface_listener_t *listener = &job->listener;
peer_cfg_t *peer_cfg = listener->peer_cfg;
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
peer_cfg); listener->peer_cfg);
peer_cfg->destroy(peer_cfg);
if (!ike_sa) if (!ike_sa)
{ {
DESTROY_IF(listener->child_cfg);
listener->status = FAILED; listener->status = FAILED;
listener_done(listener); listener_done(listener);
return JOB_REQUEUE_NONE; return JOB_REQUEUE_NONE;
@ -449,7 +448,6 @@ METHOD(job_t, initiate_execute, job_requeue_t,
"%d exceeds limit of %d", half_open, limit_half_open); "%d exceeds limit of %d", half_open, limit_half_open);
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
ike_sa); ike_sa);
DESTROY_IF(listener->child_cfg);
listener->status = INVALID_STATE; listener->status = INVALID_STATE;
listener_done(listener); listener_done(listener);
return JOB_REQUEUE_NONE; return JOB_REQUEUE_NONE;
@ -468,7 +466,6 @@ METHOD(job_t, initiate_execute, job_requeue_t,
"limit of %d", jobs, limit_job_load); "limit of %d", jobs, limit_job_load);
charon->ike_sa_manager->checkin_and_destroy( charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, ike_sa); charon->ike_sa_manager, ike_sa);
DESTROY_IF(listener->child_cfg);
listener->status = INVALID_STATE; listener->status = INVALID_STATE;
listener_done(listener); listener_done(listener);
return JOB_REQUEUE_NONE; return JOB_REQUEUE_NONE;
@ -476,6 +473,10 @@ METHOD(job_t, initiate_execute, job_requeue_t,
} }
} }
if (listener->child_cfg)
{
listener->child_cfg->get_ref(listener->child_cfg);
}
if (ike_sa->initiate(ike_sa, listener->child_cfg, NULL) == SUCCESS) if (ike_sa->initiate(ike_sa, listener->child_cfg, NULL) == SUCCESS)
{ {
if (!listener->logger.callback || if (!listener->logger.callback ||

View File

@ -480,6 +480,15 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
return TRUE; return TRUE;
} }
/**
* Clear the given chunk and free it
*/
static void destroy_request_chunk(chunk_t *chunk)
{
chunk_clear(chunk);
free(chunk);
}
/** /**
* Callback processing incoming requests in strict order * Callback processing incoming requests in strict order
*/ */
@ -487,7 +496,7 @@ CALLBACK(process_queue, job_requeue_t,
entry_selector_t *sel) entry_selector_t *sel)
{ {
entry_t *entry; entry_t *entry;
chunk_t chunk; chunk_t *chunk;
bool found; bool found;
u_int id; u_int id;
@ -499,7 +508,8 @@ CALLBACK(process_queue, job_requeue_t,
break; break;
} }
found = array_remove(entry->queue, ARRAY_HEAD, &chunk); INIT(chunk);
found = array_remove(entry->queue, ARRAY_HEAD, chunk);
if (!found) if (!found)
{ {
entry->has_processor = FALSE; entry->has_processor = FALSE;
@ -508,11 +518,12 @@ CALLBACK(process_queue, job_requeue_t,
put_entry(sel->this, entry, TRUE, FALSE); put_entry(sel->this, entry, TRUE, FALSE);
if (!found) if (!found)
{ {
free(chunk);
break; break;
} }
thread_cleanup_push((void*)chunk_clear, &chunk); thread_cleanup_push((void*)destroy_request_chunk, chunk);
sel->this->inbound(sel->this->user, id, chunk); sel->this->inbound(sel->this->user, id, *chunk);
thread_cleanup_pop(TRUE); thread_cleanup_pop(TRUE);
} }
return JOB_REQUEUE_NONE; return JOB_REQUEUE_NONE;
@ -552,8 +563,8 @@ CALLBACK(on_read, bool,
.id = entry->id, .id = entry->id,
); );
lib->processor->queue_job(lib->processor, lib->processor->queue_job(lib->processor,
(job_t*)callback_job_create(process_queue, (job_t*)callback_job_create(process_queue, sel,
sel, free, NULL)); free, callback_job_cancel_thread));
entry->has_processor = TRUE; entry->has_processor = TRUE;
} }
} }