kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit f4d00645ed078f4e8ddd883d37303e517d605bc8
parent 1f5e482b8a62445879daa102a958a916f8e094cf
Author: Joris Vink <joris@coders.se>
Date:   Mon,  1 Feb 2016 19:51:27 +0100

Merge pull request #99 from oneswig/master

Add resource management as part of the kore shutdown process.
Diffstat:
includes/http.h | 1+
includes/kore.h | 8++++++++
src/bsd.c | 17+++++++++++++++++
src/buf.c | 5+++++
src/cli.c | 1+
src/config.c | 2++
src/connection.c | 10++++++++++
src/domain.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/http.c | 17+++++++++++++++++
src/kore.c | 6++++++
src/linux.c | 14++++++++++++++
src/mem.c | 2+-
src/module.c | 33++++++++++++++++++++++++++++++---
src/net.c | 9++++++++-
src/pool.c | 42++++++++++++++++++++++++++++++++++++++++++
src/utils.c | 4++++
src/websocket.c | 1+
src/worker.c | 8+++++++-
18 files changed, 230 insertions(+), 6 deletions(-)

diff --git a/includes/http.h b/includes/http.h @@ -211,6 +211,7 @@ extern char *http_body_disk_path; void kore_accesslog(struct http_request *); void http_init(void); +void http_cleanup(void); void http_process(void); const char *http_status_text(int); time_t http_date_to_time(char *); diff --git a/includes/kore.h b/includes/kore.h @@ -42,6 +42,7 @@ #include <string.h> #include <syslog.h> #include <unistd.h> +#include <stdarg.h> #if defined(__cplusplus) extern "C" { @@ -433,6 +434,7 @@ struct kore_worker *kore_worker_data(u_int8_t); void kore_platform_init(void); void kore_platform_event_init(void); +void kore_platform_event_cleanup(void); void kore_platform_proctitle(char *); void kore_platform_disable_read(int); void kore_platform_enable_accept(void); @@ -468,6 +470,7 @@ void kore_tls_info_callback(const SSL *, int, int); #endif void kore_connection_init(void); +void kore_connection_cleanup(void); void kore_connection_prune(int); struct connection *kore_connection_new(void *); void kore_connection_check_timeout(void); @@ -496,6 +499,7 @@ void *kore_pool_get(struct kore_pool *); void kore_pool_put(struct kore_pool *, void *); void kore_pool_init(struct kore_pool *, const char *, u_int32_t, u_int32_t); +void kore_pool_cleanup(struct kore_pool *); time_t kore_date_to_time(char *); char *kore_time_to_date(time_t); @@ -531,7 +535,9 @@ int kore_msg_register(u_int8_t, void (*cb)(struct kore_msg *, const void *)); void kore_domain_init(void); +void kore_domain_cleanup(void); int kore_domain_new(char *); +void kore_domain_free(struct kore_domain *); void kore_module_init(void); void kore_module_reload(int); void kore_module_onload(void); @@ -543,6 +549,7 @@ void kore_module_load(const char *, const char *); void kore_domain_sslstart(struct kore_domain *); int kore_module_handler_new(const char *, const char *, const char *, const char *, int); +void kore_module_handler_free(struct kore_module_handle *); struct kore_domain *kore_domain_lookup(const char *); struct kore_module_handle *kore_module_handler_find(const char *, @@ -569,6 +576,7 @@ void net_write32(u_int8_t *, u_int32_t); void net_write64(u_int8_t *, u_int64_t); void net_init(void); +void net_cleanup(void); int net_send(struct connection *); int net_send_flush(struct connection *); int net_recv_flush(struct connection *); diff --git a/src/bsd.c b/src/bsd.c @@ -22,6 +22,9 @@ #include <sys/cpuset.h> #endif +#include <errno.h> +#include <string.h> + #include "kore.h" #if defined(KORE_USE_PGSQL) @@ -91,6 +94,20 @@ kore_platform_event_init(void) } } +void +kore_platform_event_cleanup(void) +{ + if (kfd >= 0) { + close(kfd); + kfd = -1; + } + + if (events != NULL) { + kore_mem_free(events); + events = NULL; + } +} + int kore_platform_event_wait(u_int64_t timer) { diff --git a/src/buf.c b/src/buf.c @@ -14,6 +14,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> + #include "kore.h" struct kore_buf * diff --git a/src/cli.c b/src/cli.c @@ -20,6 +20,7 @@ #include <sys/queue.h> #include <sys/wait.h> #include <sys/mman.h> +#include <sys/time.h> #include <openssl/pem.h> #include <openssl/x509v3.h> diff --git a/src/config.c b/src/config.c @@ -16,6 +16,8 @@ #include <sys/stat.h> +#include <stdio.h> +#include <string.h> #include <ctype.h> #include <limits.h> #include <fcntl.h> diff --git a/src/connection.c b/src/connection.c @@ -38,6 +38,16 @@ kore_connection_init(void) sizeof(struct connection), worker_max_connections); } +void +kore_connection_cleanup(void) +{ + kore_debug("connection_cleanup()"); + + /* Drop all connections */ + kore_connection_prune(KORE_CONNECTION_PRUNE_ALL); + kore_pool_cleanup(&connection_pool); +} + struct connection * kore_connection_new(void *owner) { diff --git a/src/domain.c b/src/domain.c @@ -42,6 +42,17 @@ kore_domain_init(void) TAILQ_INIT(&domains); } +void +kore_domain_cleanup(void) +{ + struct kore_domain *dom; + + while ((dom=TAILQ_FIRST(&domains)) != NULL) { + TAILQ_REMOVE(&domains, dom, list); + kore_domain_free(dom); + } +} + int kore_domain_new(char *domain) { @@ -72,6 +83,49 @@ kore_domain_new(char *domain) } void +kore_domain_free(struct kore_domain *dom) +{ + struct kore_module_handle *hdlr; + + if (dom != NULL) { + + if (primary_dom == dom) { + primary_dom = NULL; + } + TAILQ_REMOVE(&domains, dom, list); + + if (dom->domain != NULL) { + kore_mem_free(dom->domain); + } + +#if !defined(KORE_NO_TLS) + if (dom->ssl_ctx != NULL) { + SSL_CTX_free(dom->ssl_ctx); + } + if (dom->cafile != NULL) { + kore_mem_free(dom->cafile); + } + if (dom->certkey != NULL) { + kore_mem_free(dom->certkey); + } + if (dom->certfile != NULL) { + kore_mem_free(dom->certfile); + } + if (dom->crlfile != NULL) { + kore_mem_free(dom->crlfile); + } +#endif + + /* Drop all handlers associated with this domain */ + while ((hdlr=TAILQ_FIRST(&(dom->handlers))) != NULL) { + TAILQ_REMOVE(&(dom->handlers), hdlr, list); + kore_module_handler_free(hdlr); + } + kore_mem_free(dom); + } +} + +void kore_domain_sslstart(struct kore_domain *dom) { #if !defined(KORE_NO_TLS) @@ -179,7 +233,9 @@ kore_domain_sslstart(struct kore_domain *dom) SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb); kore_mem_free(dom->certfile); + dom->certfile = NULL; kore_mem_free(dom->certkey); + dom->certkey = NULL; #endif } diff --git a/src/http.c b/src/http.c @@ -18,6 +18,8 @@ #include <ctype.h> #include <inttypes.h> +#include <stdio.h> +#include <string.h> #include <fcntl.h> #include <unistd.h> @@ -101,6 +103,21 @@ http_init(void) "http_body_path", HTTP_BODY_PATH_MAX, prealloc); } +void +http_cleanup(void) +{ + if (header_buf != NULL) { + kore_buf_free(header_buf); + header_buf = NULL; + } + + kore_pool_cleanup(&http_request_pool); + kore_pool_cleanup(&http_header_pool); + kore_pool_cleanup(&http_host_pool); + kore_pool_cleanup(&http_path_pool); + kore_pool_cleanup(&http_body_path); +} + int http_request_new(struct connection *c, const char *host, const char *method, const char *path, const char *version, diff --git a/src/kore.c b/src/kore.c @@ -20,6 +20,7 @@ #include <sys/socket.h> #include <sys/resource.h> +#include <stdio.h> #include <netdb.h> #include <signal.h> @@ -417,6 +418,11 @@ kore_server_start(void) kore_platform_event_wait(100); kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT); } + + kore_platform_event_cleanup(); + kore_connection_cleanup(); + kore_domain_cleanup(); + net_cleanup(); } static void diff --git a/src/linux.c b/src/linux.c @@ -71,6 +71,20 @@ kore_platform_event_init(void) events = kore_calloc(event_count, sizeof(struct epoll_event)); } +void +kore_platform_event_cleanup(void) +{ + if (efd >= 0) { + close(efd); + efd = -1; + } + + if (events != NULL) { + kore_mem_free(events); + events = NULL; + } +} + int kore_platform_event_wait(u_int64_t timer) { diff --git a/src/mem.c b/src/mem.c @@ -50,7 +50,7 @@ kore_malloc(size_t len) mlen = sizeof(u_int32_t) + len + sizeof(struct meminfo); if ((ptr = calloc(1, mlen)) == NULL) - fatal("kore_malloc(%d): %d", len, errno); + fatal("kore_malloc(%zd): %d", len, errno); plen = (u_int32_t *)ptr; *plen = len; diff --git a/src/module.c b/src/module.c @@ -186,9 +186,7 @@ kore_module_handler_new(const char *path, const char *domain, if (hdlr->type == HANDLER_TYPE_DYNAMIC) { if (regcomp(&(hdlr->rctx), hdlr->path, REG_EXTENDED | REG_NOSUB)) { - kore_mem_free(hdlr->func); - kore_mem_free(hdlr->path); - kore_mem_free(hdlr); + kore_module_handler_free(hdlr); kore_debug("regcomp() on %s failed", path); return (KORE_RESULT_ERROR); } @@ -198,6 +196,35 @@ kore_module_handler_new(const char *path, const char *domain, return (KORE_RESULT_OK); } +void +kore_module_handler_free(struct kore_module_handle *hdlr) +{ + struct kore_handler_params *param; + + if (hdlr != NULL) { + if (hdlr->func != NULL) { + kore_mem_free(hdlr->func); + } + if (hdlr->path != NULL) { + kore_mem_free(hdlr->path); + } + if (hdlr->dom != NULL) { + TAILQ_REMOVE(&(hdlr->dom->handlers), hdlr, list); + } + regfree(&(hdlr->rctx)); + + /* Drop all validators associated with this handler */ + while ((param=TAILQ_FIRST(&(hdlr->params))) != NULL) { + TAILQ_REMOVE(&(hdlr->params), param, list); + if (param->name != NULL) { + kore_mem_free(param->name); + } + kore_mem_free(param); + } + kore_mem_free(hdlr); + } +} + struct kore_module_handle * kore_module_handler_find(const char *domain, const char *path) { diff --git a/src/net.c b/src/net.c @@ -37,6 +37,13 @@ net_init(void) } void +net_cleanup(void) +{ + kore_debug("net_cleanup()"); + kore_pool_cleanup(&nb_pool); +} + +void net_send_queue(struct connection *c, const void *data, u_int32_t len) { const u_int8_t *d; @@ -54,7 +61,7 @@ net_send_queue(struct connection *c, const void *data, u_int32_t len) memcpy(nb->buf + nb->b_len, d, len); nb->b_len += len; return; - } else if (len > avail) { + } else { memcpy(nb->buf + nb->b_len, d, avail); nb->b_len += avail; diff --git a/src/pool.c b/src/pool.c @@ -22,6 +22,7 @@ #define POOL_ELEMENT_FREE 1 static void pool_region_create(struct kore_pool *, u_int32_t); +static void pool_region_destroy(struct kore_pool *); void kore_pool_init(struct kore_pool *pool, const char *name, @@ -41,6 +42,27 @@ kore_pool_init(struct kore_pool *pool, const char *name, pool_region_create(pool, elm); } +void +kore_pool_cleanup(struct kore_pool *pool) +{ + if (pool->inuse) + kore_debug("Pool %s: destroyed with %u allocs in use", + pool->name ? pool->name : "<unknown>", + pool->inuse ); + + pool->elms = 0; + pool->inuse = 0; + pool->elen = 0; + pool->slen = 0; + + if (pool->name != NULL) { + kore_mem_free(pool->name); + pool->name = NULL; + } + + pool_region_destroy(pool); +} + void * kore_pool_get(struct kore_pool *pool) { @@ -111,3 +133,23 @@ pool_region_create(struct kore_pool *pool, u_int32_t elms) pool->elms += elms; } + +static void +pool_region_destroy(struct kore_pool *pool) +{ + struct kore_pool_region *reg; + + kore_debug("pool_region_destroy(%p)", pool); + + /* Take care iterating when modifying list contents */ + while (!LIST_EMPTY(&pool->regions)) { + reg = LIST_FIRST(&pool->regions); + LIST_REMOVE(reg, list); + kore_mem_free(reg->start); + kore_mem_free(reg); + } + + /* Freelist references into the regions memory allocations */ + LIST_INIT(&pool->freelist); + pool->elms = 0; +} diff --git a/src/utils.c b/src/utils.c @@ -16,6 +16,10 @@ #include <sys/time.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> #include <time.h> #include <limits.h> diff --git a/src/websocket.c b/src/websocket.c @@ -19,6 +19,7 @@ #include <openssl/sha.h> #include <limits.h> +#include <string.h> #include "kore.h" #include "http.h" diff --git a/src/worker.c b/src/worker.c @@ -368,7 +368,13 @@ kore_worker_entry(struct kore_worker *kw) #endif } - kore_connection_prune(KORE_CONNECTION_PRUNE_ALL); + kore_platform_event_cleanup(); + kore_connection_cleanup(); + kore_domain_cleanup(); +#if !defined(KORE_NO_HTTP) + http_cleanup(); +#endif + net_cleanup(); kore_debug("worker %d shutting down", kw->id); exit(0); }