From ecc4b510488feca208ad651ebdef9d56966aa6f5 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 11 Feb 2014 15:09:08 +0100 Subject: [PATCH] vici: Support thread cancellation in command callbacks --- src/libcharon/plugins/vici/vici_dispatcher.c | 68 ++++++++++++++------ src/libcharon/plugins/vici/vici_socket.c | 4 +- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/libcharon/plugins/vici/vici_dispatcher.c b/src/libcharon/plugins/vici/vici_dispatcher.c index 982206af1..b66d0d5e8 100644 --- a/src/libcharon/plugins/vici/vici_dispatcher.c +++ b/src/libcharon/plugins/vici/vici_dispatcher.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -184,40 +185,69 @@ static void unregister_event(private_vici_dispatcher_t *this, char *name, } } +/** + * Data to release on thread cancellation + */ +typedef struct { + private_vici_dispatcher_t *this; + command_t *cmd; + vici_message_t *request; +} release_data_t; + +/** + * Release command after execution/cancellation + */ +CALLBACK(release_command, void, + release_data_t *release) +{ + release->request->destroy(release->request); + + release->this->mutex->lock(release->this->mutex); + if (--release->cmd->uses == 0) + { + release->this->cond->broadcast(release->this->cond); + } + release->this->mutex->unlock(release->this->mutex); + + free(release); +} + /** * Process a request message */ void process_request(private_vici_dispatcher_t *this, char *name, u_int id, chunk_t data) { - command_t *cmd; - vici_message_t *request, *response = NULL; + vici_message_t *response = NULL; + release_data_t *release; + + INIT(release, + .this = this, + ); this->mutex->lock(this->mutex); - cmd = this->cmds->get(this->cmds, name); - if (cmd) + release->cmd = this->cmds->get(this->cmds, name); + if (release->cmd) { - cmd->uses++; + release->cmd->uses++; } this->mutex->unlock(this->mutex); - if (cmd) + if (release->cmd) { - request = vici_message_create_from_data(data, FALSE); - response = cmd->cb(cmd->user, cmd->name, id, request); - request->destroy(request); + thread_cleanup_push(release_command, release); - this->mutex->lock(this->mutex); - if (--cmd->uses == 0) + release->request = vici_message_create_from_data(data, FALSE); + response = release->cmd->cb(release->cmd->user, release->cmd->name, + id, release->request); + + thread_cleanup_pop(TRUE); + + if (response) { - this->cond->broadcast(this->cond); + send_op(this, id, VICI_CMD_RESPONSE, NULL, response); + response->destroy(response); } - this->mutex->unlock(this->mutex); - } - if (response) - { - send_op(this, id, VICI_CMD_RESPONSE, NULL, response); - response->destroy(response); } else { @@ -264,7 +294,9 @@ CALLBACK(inbound, void, if (reader->read_data8(reader, &chunk) && vici_stringify(chunk, name, sizeof(name))) { + thread_cleanup_push((void*)reader->destroy, reader); process_request(this, name, id, reader->peek(reader)); + thread_cleanup_pop(FALSE); } else { diff --git a/src/libcharon/plugins/vici/vici_socket.c b/src/libcharon/plugins/vici/vici_socket.c index 6cb445b2a..b2251982e 100644 --- a/src/libcharon/plugins/vici/vici_socket.c +++ b/src/libcharon/plugins/vici/vici_socket.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -374,8 +375,9 @@ CALLBACK(on_read, bool, if (data.len) { + thread_cleanup_push(free, data.ptr); entry->this->inbound(entry->this->user, entry->id, data); - chunk_clear(&data); + thread_cleanup_pop(TRUE); } return ret;