commit b4a0330a96ec1790590e1d2a50c786d7da652509
parent 1582528ba5d8e077c53b3cc5b43b7c56c9a51abe
Author: Joris Vink <joris@coders.se>
Date: Thu, 27 Jun 2013 08:43:07 +0200
- Better spread load between all worker processes.
- Introduce own memory management system on top of malloc to keep track
of all our allocations and free's. Later we should introduce a pooling
mechanism for fixed size allocations (http_request comes to mind).
- Introduce ssl_cipher in configuration.
Memory usage is kind of high right now, but it seems its OpenSSL
doing it rather then Kore.
Diffstat:
16 files changed, 341 insertions(+), 191 deletions(-)
diff --git a/Makefile b/Makefile
@@ -5,7 +5,7 @@ BIN=kore
S_SRC+= src/kore.c src/buf.c src/config.c src/net.c src/spdy.c src/http.c \
src/accesslog.c src/domain.c src/module.c src/utils.c \
- src/worker.c src/connection.c src/zlib_dict.c
+ src/worker.c src/connection.c src/mem.c src/zlib_dict.c
S_OBJS= $(S_SRC:.c=.o)
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes
diff --git a/includes/http.h b/includes/http.h
@@ -49,8 +49,8 @@ struct http_request {
int status;
u_int64_t start;
u_int64_t end;
- char *host;
- char *path;
+ char host[KORE_DOMAINNAME_LEN];
+ char path[HTTP_URI_LEN];
char *agent;
struct connection *owner;
struct spdy_stream *stream;
diff --git a/includes/kore.h b/includes/kore.h
@@ -29,8 +29,9 @@
#define errno_s strerror(errno)
#define ssl_errno_s ERR_error_string(ERR_get_error(), NULL)
-#define KORE_DOMAINNAME_LEN 254
-#define KORE_PIDFILE_DEFAULT "/var/run/kore.pid"
+#define KORE_DOMAINNAME_LEN 254
+#define KORE_PIDFILE_DEFAULT "/var/run/kore.pid"
+#define KORE_DEFAULT_CIPHER_LIST "HIGH:!aNULL:!MD5;"
#define kore_debug(fmt, ...) \
if (kore_debug) \
@@ -76,12 +77,12 @@ struct listener {
struct connection {
int fd;
- int state;
- int proto;
+ u_int8_t state;
+ u_int8_t proto;
struct sockaddr_in sin;
void *owner;
SSL *ssl;
- int flags;
+ u_int8_t flags;
u_int8_t inflate_started;
z_stream z_inflate;
@@ -111,11 +112,13 @@ struct kore_module_handle {
};
struct kore_worker {
- u_int16_t id;
- u_int16_t cpu;
+ u_int8_t id;
+ u_int8_t cpu;
u_int16_t load;
pid_t pid;
- TAILQ_ENTRY(kore_worker) list;
+ u_int8_t has_lock;
+ u_int16_t accepted;
+ u_int16_t accept_treshold;
};
struct kore_domain {
@@ -154,7 +157,9 @@ extern char *kore_module_onload;
extern char *kore_pidfile;
extern char *config_file;
extern char kore_version_string[];
+extern char *kore_ssl_cipher_list;
+extern u_int32_t meminuse;
extern u_int16_t cpu_count;
extern u_int8_t worker_count;
extern u_int32_t worker_max_connections;
@@ -176,7 +181,7 @@ void kore_worker_connection_move(struct connection *);
void kore_worker_connection_remove(struct connection *);
void kore_platform_event_init(void);
-int kore_platform_event_wait(void);
+void kore_platform_event_wait(void);
void kore_platform_proctitle(char *);
void kore_platform_enable_accept(void);
void kore_platform_disable_accept(void);
@@ -200,10 +205,15 @@ int kore_connection_accept(struct listener *, struct connection **);
u_int64_t kore_time_ms(void);
void kore_log_init(void);
+
void *kore_malloc(size_t);
void kore_parse_config(void);
void *kore_calloc(size_t, size_t);
void *kore_realloc(void *, size_t);
+void kore_mem_free(void *);
+void kore_mem_init(void);
+void kore_mem_dump(void);
+
time_t kore_date_to_time(char *);
char *kore_time_to_date(time_t);
char *kore_strdup(const char *);
diff --git a/src/buf.c b/src/buf.c
@@ -105,7 +105,7 @@ kore_buf_release(struct kore_buf *buf, u_int32_t *len)
p = buf->data;
*len = buf->offset;
- free(buf);
+ kore_mem_free(buf);
return (p);
}
diff --git a/src/config.c b/src/config.c
@@ -52,6 +52,7 @@ static int configure_accesslog(char **);
static int configure_certfile(char **);
static int configure_certkey(char **);
static int configure_max_connections(char **);
+static int configure_ssl_cipher(char **);
static void domain_sslstart(void);
static struct {
@@ -63,6 +64,7 @@ static struct {
{ "onload", configure_onload },
{ "static", configure_handler },
{ "dynamic", configure_handler },
+ { "ssl_cipher", configure_ssl_cipher },
{ "domain", configure_domain },
{ "chroot", configure_chroot },
{ "runas", configure_runas },
@@ -186,6 +188,21 @@ configure_onload(char **argv)
}
static int
+configure_ssl_cipher(char **argv)
+{
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ if (strcmp(kore_ssl_cipher_list, KORE_DEFAULT_CIPHER_LIST)) {
+ kore_debug("duplicate ssl_cipher directive specified");
+ return (KORE_RESULT_ERROR);
+ }
+
+ kore_ssl_cipher_list = kore_strdup(argv[1]);
+ return (KORE_RESULT_OK);
+}
+
+static int
configure_domain(char **argv)
{
if (argv[2] == NULL)
diff --git a/src/connection.c b/src/connection.c
@@ -57,14 +57,14 @@ kore_connection_accept(struct listener *l, struct connection **out)
len = sizeof(struct sockaddr_in);
c = (struct connection *)kore_malloc(sizeof(*c));
if ((c->fd = accept(l->fd, (struct sockaddr *)&(c->sin), &len)) == -1) {
- free(c);
+ kore_mem_free(c);
kore_debug("accept(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
if (!kore_connection_nonblock(c->fd)) {
close(c->fd);
- free(c);
+ kore_mem_free(c);
return (KORE_RESULT_ERROR);
}
@@ -194,15 +194,16 @@ kore_connection_remove(struct connection *c)
for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = next) {
next = TAILQ_NEXT(nb, list);
TAILQ_REMOVE(&(c->send_queue), nb, list);
- free(nb->buf);
- free(nb);
+ if (nb->buf != NULL)
+ kore_mem_free(nb->buf);
+ kore_mem_free(nb);
}
for (nb = TAILQ_FIRST(&(c->recv_queue)); nb != NULL; nb = next) {
next = TAILQ_NEXT(nb, list);
TAILQ_REMOVE(&(c->recv_queue), nb, list);
- free(nb->buf);
- free(nb);
+ kore_mem_free(nb->buf);
+ kore_mem_free(nb);
}
for (s = TAILQ_FIRST(&(c->spdy_streams)); s != NULL; s = snext) {
@@ -211,15 +212,15 @@ kore_connection_remove(struct connection *c)
if (s->hblock != NULL) {
if (s->hblock->header_block != NULL)
- free(s->hblock->header_block);
- free(s->hblock);
+ kore_mem_free(s->hblock->header_block);
+ kore_mem_free(s->hblock);
}
- free(s);
+ kore_mem_free(s);
}
kore_worker_connection_remove(c);
- free(c);
+ kore_mem_free(c);
}
int
diff --git a/src/domain.c b/src/domain.c
@@ -58,12 +58,13 @@ kore_domain_new(char *domain)
if (kore_domain_lookup(domain) != NULL)
return (KORE_RESULT_ERROR);
- kore_debug("kore_domain_new(%s, %s, %s)", domain);
+ kore_debug("kore_domain_new(%s)", domain);
dom = (struct kore_domain *)kore_malloc(sizeof(*dom));
dom->accesslog = -1;
dom->certfile = NULL;
dom->certkey = NULL;
+ dom->ssl_ctx = NULL;
dom->domain = kore_strdup(domain);
TAILQ_INIT(&(dom->handlers));
TAILQ_INSERT_TAIL(&domains, dom, list);
@@ -81,7 +82,7 @@ kore_domain_sslstart(struct kore_domain *dom)
dom->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
if (dom->ssl_ctx == NULL)
- fatal("kore_domain_new(): SSL_ctx_new(): %s", ssl_errno_s);
+ fatal("kore_domain_sslstart(): SSL_ctx_new(): %s", ssl_errno_s);
if (!SSL_CTX_use_certificate_chain_file(dom->ssl_ctx, dom->certfile)) {
fatal("SSL_CTX_use_certificate_chain_file(%s): %s",
dom->certfile, ssl_errno_s);
@@ -96,15 +97,16 @@ kore_domain_sslstart(struct kore_domain *dom)
if (!SSL_CTX_check_private_key(dom->ssl_ctx))
fatal("Public/Private key for %s do not match", dom->domain);
- SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_AUTO_RETRY);
+ SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
+ SSL_CTX_set_cipher_list(dom->ssl_ctx, kore_ssl_cipher_list);
SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_ssl_sni_cb);
SSL_CTX_set_next_protos_advertised_cb(dom->ssl_ctx,
kore_ssl_npn_cb, NULL);
- free(dom->certfile);
- free(dom->certkey);
+ kore_mem_free(dom->certfile);
+ kore_mem_free(dom->certkey);
}
struct kore_domain *
diff --git a/src/http.c b/src/http.c
@@ -75,8 +75,9 @@ http_request_new(struct connection *c, struct spdy_stream *s, char *host,
req->status = 0;
req->stream = s;
req->post_data = NULL;
- req->host = kore_strdup(host);
- req->path = kore_strdup(path);
+ kore_strlcpy(req->host, host, sizeof(req->host));
+ kore_strlcpy(req->path, path, sizeof(req->path));
+
TAILQ_INIT(&(req->resp_headers));
TAILQ_INIT(&(req->req_headers));
TAILQ_INIT(&(req->arguments));
@@ -180,35 +181,33 @@ http_request_free(struct http_request *req)
next = TAILQ_NEXT(hdr, list);
TAILQ_REMOVE(&(req->resp_headers), hdr, list);
- free(hdr->header);
- free(hdr->value);
- free(hdr);
+ kore_mem_free(hdr->header);
+ kore_mem_free(hdr->value);
+ kore_mem_free(hdr);
}
for (hdr = TAILQ_FIRST(&(req->req_headers)); hdr != NULL; hdr = next) {
next = TAILQ_NEXT(hdr, list);
TAILQ_REMOVE(&(req->req_headers), hdr, list);
- free(hdr->header);
- free(hdr->value);
- free(hdr);
+ kore_mem_free(hdr->header);
+ kore_mem_free(hdr->value);
+ kore_mem_free(hdr);
}
for (q = TAILQ_FIRST(&(req->arguments)); q != NULL; q = qnext) {
qnext = TAILQ_NEXT(q, list);
TAILQ_REMOVE(&(req->arguments), q, list);
- free(q->name);
+ kore_mem_free(q->name);
if (q->value != NULL)
- free(q->value);
- free(q);
+ kore_mem_free(q->value);
+ kore_mem_free(q);
}
- free(req->path);
- free(req->host);
if (req->agent != NULL)
- free(req->agent);
- free(req);
+ kore_mem_free(req->agent);
+ kore_mem_free(req);
}
int
@@ -241,7 +240,7 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len)
spdy_frame_send(req->owner, SPDY_CTRL_FRAME_SYN_REPLY,
0, hlen, req->stream, 0);
net_send_queue(req->owner, htext, hlen, 0, NULL, NULL);
- free(htext);
+ kore_mem_free(htext);
if (len > 0) {
spdy_frame_send(req->owner, SPDY_DATA_FRAME,
@@ -267,7 +266,7 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len)
kore_buf_append(buf, (u_int8_t *)"\r\n", 2);
htext = kore_buf_release(buf, &hlen);
net_send_queue(req->owner, htext, hlen, 0, NULL, NULL);
- free(htext);
+ kore_mem_free(htext);
net_send_queue(req->owner, d, len, 0, NULL, http_send_done);
}
@@ -332,19 +331,19 @@ http_header_recv(struct netbuf *nb)
h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
if (h < 2) {
- free(hbuf);
+ kore_mem_free(hbuf);
return (KORE_RESULT_ERROR);
}
if ((strlen(headers[0]) > 3 && strncasecmp(headers[0], "get", 3)) &&
(strlen(headers[0]) > 4 && strncasecmp(headers[0], "post", 4))) {
- free(hbuf);
+ kore_mem_free(hbuf);
return (KORE_RESULT_ERROR);
}
v = kore_split_string(headers[0], " ", request, 4);
if (v != 3) {
- free(hbuf);
+ kore_mem_free(hbuf);
return (KORE_RESULT_ERROR);
}
@@ -356,13 +355,13 @@ http_header_recv(struct netbuf *nb)
v = kore_split_string(headers[i], ":", host, 3);
if (v != 2) {
- free(hbuf);
+ kore_mem_free(hbuf);
return (KORE_RESULT_ERROR);
}
if (strlen(host[0]) != 4 || strncasecmp(host[0], "host", 4) ||
strlen(host[1]) < 4) {
- free(hbuf);
+ kore_mem_free(hbuf);
return (KORE_RESULT_ERROR);
}
@@ -372,12 +371,12 @@ http_header_recv(struct netbuf *nb)
}
if (host[0] == NULL) {
- free(hbuf);
+ kore_mem_free(hbuf);
return (KORE_RESULT_ERROR);
}
if (!http_request_new(c, NULL, host[1], request[0], request[1], &req)) {
- free(hbuf);
+ kore_mem_free(hbuf);
return (KORE_RESULT_ERROR);
}
@@ -404,7 +403,7 @@ http_header_recv(struct netbuf *nb)
req->agent = kore_strdup(hdr->value);
}
- free(hbuf);
+ kore_mem_free(hbuf);
if (req->method == HTTP_METHOD_POST) {
if (!http_request_header_get(req, "content-length", &p)) {
@@ -415,13 +414,13 @@ http_header_recv(struct netbuf *nb)
clen = kore_strtonum(p, 0, UINT_MAX, &v);
if (v == KORE_RESULT_ERROR) {
- free(p);
+ kore_mem_free(p);
kore_debug("content-length invalid: %s", p);
req->flags |= HTTP_REQUEST_DELETE;
return (KORE_RESULT_ERROR);
}
- free(p);
+ kore_mem_free(p);
req->post_data = kore_buf_create(clen);
kore_buf_append(req->post_data, end_headers,
(nb->offset - len));
@@ -468,7 +467,7 @@ http_populate_arguments(struct http_request *req)
count++;
}
- free(query);
+ kore_mem_free(query);
return (count);
}
@@ -501,7 +500,7 @@ http_post_data_text(struct http_request *req)
text = (char *)kore_malloc(len);
kore_strlcpy(text, (char *)data, len);
- free(data);
+ kore_mem_free(data);
return (text);
}
diff --git a/src/kore.c b/src/kore.c
@@ -58,6 +58,7 @@ char *runas_user = NULL;
char *chroot_path = NULL;
char kore_version_string[32];
char *kore_pidfile = KORE_PIDFILE_DEFAULT;
+char *kore_ssl_cipher_list = KORE_DEFAULT_CIPHER_LIST;
static void usage(void);
static void kore_server_start(void);
@@ -97,10 +98,12 @@ main(int argc, char *argv[])
argv += optind;
kore_pid = getpid();
+
+ kore_mem_init();
kore_domain_init();
kore_server_sslstart();
-
kore_parse_config();
+
kore_log_init();
kore_platform_init();
kore_accesslog_init();
@@ -162,6 +165,9 @@ kore_server_sslstart(void)
SSL_library_init();
SSL_load_error_strings();
+
+CRYPTO_malloc_debug_init();
+CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
}
static void
@@ -170,8 +176,8 @@ kore_server_start(void)
if (!kore_server_bind(&server, server_ip, server_port))
fatal("cannot bind to %s:%d", server_ip, server_port);
- free(server_ip);
- free(runas_user);
+ kore_mem_free(server_ip);
+ kore_mem_free(runas_user);
if (daemon(1, 1) == -1)
fatal("cannot daemon(): %s", errno_s);
diff --git a/src/linux.c b/src/linux.c
@@ -45,9 +45,8 @@
#include "kore.h"
#include "http.h"
-#define EPOLL_EVENTS 500
-
static int efd = -1;
+static u_int32_t event_count = 0;
static struct epoll_event *events = NULL;
void
@@ -80,26 +79,26 @@ kore_platform_event_init(void)
if ((efd = epoll_create(10000)) == -1)
fatal("epoll_create(): %s", errno_s);
- events = kore_calloc(EPOLL_EVENTS, sizeof(struct epoll_event));
+ event_count = worker_max_connections + 1;
+ events = kore_calloc(event_count, sizeof(struct epoll_event));
}
-int
+void
kore_platform_event_wait(void)
{
struct connection *c;
- int n, i, *fd, count;
+ int n, i, *fd;
- n = epoll_wait(efd, events, EPOLL_EVENTS, 100);
+ n = epoll_wait(efd, events, event_count, 100);
if (n == -1) {
if (errno == EINTR)
- return (0);
+ return;
fatal("epoll_wait(): %s", errno_s);
}
if (n > 0)
kore_debug("main(): %d sockets available", n);
- count = 0;
for (i = 0; i < n; i++) {
fd = (int *)events[i].data.ptr;
@@ -114,13 +113,16 @@ kore_platform_event_wait(void)
}
if (*fd == server.fd) {
+#if 0
while (worker_active_connections <
worker_max_connections) {
+#endif
+ while (worker->accepted < worker->accept_treshold) {
kore_connection_accept(&server, &c);
if (c == NULL)
break;
- count++;
+ worker->accepted++;
kore_platform_event_schedule(c->fd,
EPOLLIN | EPOLLOUT | EPOLLET, 0, c);
}
@@ -135,8 +137,6 @@ kore_platform_event_wait(void)
kore_connection_disconnect(c);
}
}
-
- return (count);
}
void
diff --git a/src/mem.c b/src/mem.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2013 Joris Vink <joris@coders.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <regex.h>
+#include <zlib.h>
+
+#include "spdy.h"
+#include "kore.h"
+
+#define KORE_MEM_MAGIC 0xd0d0
+#define KORE_MEMINFO(x) \
+ ((struct meminfo *)((u_int8_t *)x - sizeof(struct meminfo)))
+
+struct meminfo {
+ u_int32_t id;
+ u_int32_t len;
+ u_int32_t clen;
+ u_int64_t t;
+ TAILQ_ENTRY(meminfo) list;
+ u_int16_t magic;
+ u_int8_t *addr;
+};
+
+static u_int64_t memid;
+u_int32_t meminuse;
+TAILQ_HEAD(, meminfo) memused;
+
+void
+kore_mem_init(void)
+{
+ memid = 0;
+ meminuse = 0;
+ TAILQ_INIT(&memused);
+}
+
+void *
+kore_malloc(size_t len)
+{
+ size_t mlen;
+ struct meminfo *mem;
+
+ mlen = sizeof(struct meminfo) + len;
+ if ((mem = (struct meminfo *)malloc(mlen)) == NULL)
+ fatal("kore_malloc(%d): %d", len, errno);
+
+ mem->clen = len;
+ mem->len = mlen;
+ mem->id = memid++;
+ mem->t = kore_time_ms();
+ mem->addr = (u_int8_t *)mem + sizeof(struct meminfo);
+ mem->magic = KORE_MEM_MAGIC;
+ TAILQ_INSERT_TAIL(&memused, mem, list);
+ if ((u_int8_t *)mem != mem->addr - sizeof(struct meminfo))
+ fatal("kore_malloc(): addr offset is wrong");
+
+ meminuse += len;
+ memset(mem->addr, '\0', mem->clen);
+
+ return (mem->addr);
+}
+
+void *
+kore_realloc(void *ptr, size_t len)
+{
+ struct meminfo *mem;
+ void *nptr;
+
+ mem = KORE_MEMINFO(ptr);
+ if (mem->magic != KORE_MEM_MAGIC)
+ fatal("kore_realloc(): magic boundary not found");
+
+ nptr = kore_malloc(len);
+ memcpy(nptr, mem->addr, mem->clen);
+ kore_mem_free(mem);
+
+ mem = (struct meminfo *)nptr - sizeof(*mem);
+ return (mem->addr);
+}
+
+void *
+kore_calloc(size_t memb, size_t len)
+{
+ return (kore_malloc(memb * len));
+}
+
+void
+kore_mem_free(void *ptr)
+{
+ struct meminfo *mem;
+
+ mem = KORE_MEMINFO(ptr);
+ if (mem->magic != KORE_MEM_MAGIC)
+ fatal("kore_mem_free(): magic boundary not found");
+
+ //t = kore_time_ms();
+ //printf("mem#%d released, %ld ms old\n", mem->id, t - mem->t);
+
+ meminuse -= mem->clen;
+ TAILQ_REMOVE(&memused, mem, list);
+ free(mem);
+}
+
+void
+kore_mem_dump(void)
+{
+ printf("wrk#%d: %d bytes in use\n", worker->id, meminuse);
+
+#if 0
+ now = kore_time_ms();
+ TAILQ_FOREACH(mem, &memused, list) {
+ length = now - mem->t;
+ printf("wrk#%d: mem#%d %d bytes (%ld ms)\n",
+ worker->id, mem->id, mem->clen, length);
+ }
+#endif
+}
+
+char *
+kore_strdup(const char *str)
+{
+ size_t len;
+ char *nstr;
+
+ len = strlen(str) + 1;
+ nstr = (char *)kore_malloc(len);
+ kore_strlcpy(nstr, str, len);
+
+ return (nstr);
+}
diff --git a/src/module.c b/src/module.c
@@ -141,9 +141,9 @@ kore_module_handler_new(char *path, char *domain, char *func, int type)
if (hdlr->type == HANDLER_TYPE_DYNAMIC) {
if (regcomp(&(hdlr->rctx), hdlr->path, REG_NOSUB)) {
- free(hdlr->func);
- free(hdlr->path);
- free(hdlr);
+ kore_mem_free(hdlr->func);
+ kore_mem_free(hdlr->path);
+ kore_mem_free(hdlr);
kore_debug("regcomp() on %s failed", path);
return (KORE_RESULT_ERROR);
}
diff --git a/src/net.c b/src/net.c
@@ -149,8 +149,8 @@ net_send(struct connection *c)
if (nb->offset == nb->len) {
if (nb->buf != NULL)
- free(nb->buf);
- free(nb);
+ kore_mem_free(nb->buf);
+ kore_mem_free(nb);
}
if (r != KORE_RESULT_OK)
@@ -199,7 +199,8 @@ net_recv(struct connection *c)
switch (r) {
case SSL_ERROR_WANT_READ:
c->flags &= ~CONN_READ_POSSIBLE;
- if (nb->flags & NETBUF_CALL_CB_ALWAYS)
+ if (nb->flags & NETBUF_CALL_CB_ALWAYS &&
+ nb-> offset > 0)
goto handle;
return (KORE_RESULT_OK);
case SSL_ERROR_WANT_WRITE:
@@ -220,8 +221,8 @@ handle:
TAILQ_REMOVE(&(c->recv_queue), nb, list);
if (!(nb->flags & NETBUF_RETAIN)) {
- free(nb->buf);
- free(nb);
+ kore_mem_free(nb->buf);
+ kore_mem_free(nb);
}
}
diff --git a/src/spdy.c b/src/spdy.c
@@ -253,13 +253,13 @@ spdy_header_block_release(struct connection *c,
net_write32(hblock->header_block, hblock->header_pairs);
if (!spdy_zlib_deflate(c, hblock->header_block, hblock->header_offset,
&deflated, len)) {
- free(hblock->header_block);
- free(hblock);
+ kore_mem_free(hblock->header_block);
+ kore_mem_free(hblock);
return (NULL);
}
- free(hblock->header_block);
- free(hblock);
+ kore_mem_free(hblock->header_block);
+ kore_mem_free(hblock);
return (deflated);
}
@@ -366,9 +366,9 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
kore_debug("compressed headers are %d bytes long", ctrl.length - 10);
if (!spdy_zlib_inflate(c, src, (ctrl.length - SPDY_SYNFRAME_SIZE),
&(s->hblock->header_block), &(s->hblock->header_block_len))) {
- free(s->hblock->header_block);
- free(s->hblock);
- free(s);
+ kore_mem_free(s->hblock->header_block);
+ kore_mem_free(s->hblock);
+ kore_mem_free(s);
return (KORE_RESULT_ERROR);
}
@@ -381,16 +381,16 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
#define GET_HEADER(n, r) \
if (!spdy_stream_get_header(s->hblock, n, r)) { \
- free(s->hblock->header_block); \
- free(s->hblock); \
- free(s); \
+ kore_mem_free(s->hblock->header_block); \
+ kore_mem_free(s->hblock); \
+ kore_mem_free(s); \
kore_debug("no such header: %s", n); \
if (path != NULL) \
- free(path); \
+ kore_mem_free(path); \
if (host != NULL) \
- free(host); \
+ kore_mem_free(host); \
if (method != NULL) \
- free(method); \
+ kore_mem_free(method); \
return (KORE_RESULT_ERROR); \
}
@@ -400,18 +400,18 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
if (!http_request_new(c, s, host, method, path,
(struct http_request **)&(s->httpreq))) {
- free(path);
- free(method);
- free(host);
- free(s->hblock->header_block);
- free(s->hblock);
- free(s);
+ kore_mem_free(path);
+ kore_mem_free(method);
+ kore_mem_free(host);
+ kore_mem_free(s->hblock->header_block);
+ kore_mem_free(s->hblock);
+ kore_mem_free(s);
return (KORE_RESULT_ERROR);
}
- free(path);
- free(method);
- free(host);
+ kore_mem_free(path);
+ kore_mem_free(method);
+ kore_mem_free(host);
c->client_stream_id = s->stream_id;
TAILQ_INSERT_TAIL(&(c->spdy_streams), s, list);
@@ -505,11 +505,11 @@ spdy_stream_close(struct connection *c, struct spdy_stream *s)
TAILQ_REMOVE(&(c->spdy_streams), s, list);
if (s->hblock != NULL) {
if (s->hblock->header_block != NULL)
- free(s->hblock->header_block);
- free(s->hblock);
+ kore_mem_free(s->hblock->header_block);
+ kore_mem_free(s->hblock);
}
- free(s);
+ kore_mem_free(s);
}
static int
diff --git a/src/utils.c b/src/utils.c
@@ -58,52 +58,6 @@ static struct {
{ NULL, 0 },
};
-void *
-kore_malloc(size_t len)
-{
- void *ptr;
-
- if ((ptr = malloc(len)) == NULL)
- fatal("kore_malloc(%d): %d", len, errno);
-
- memset(ptr, 0, len);
- return (ptr);
-}
-
-void *
-kore_realloc(void *ptr, size_t len)
-{
- void *nptr;
-
- if ((nptr = realloc(ptr, len)) == NULL)
- fatal("kore_realloc(%p, %d): %d", ptr, len, errno);
-
- return (nptr);
-}
-
-void *
-kore_calloc(size_t memb, size_t len)
-{
- void *ptr;
-
- if ((ptr = calloc(memb, len)) == NULL)
- fatal("kore_calloc(%d, %d): %d", memb, len, errno);
-
- memset(ptr, 0, memb * len);
- return (ptr);
-}
-
-char *
-kore_strdup(const char *str)
-{
- char *nstr;
-
- if ((nstr = strdup(str)) == NULL)
- fatal("kore_strdup(): %d", errno);
-
- return (nstr);
-}
-
void
kore_debug_internal(char *file, int line, const char *fmt, ...)
{
@@ -278,7 +232,7 @@ kore_date_to_time(char *http_date)
}
out:
- free(sdup);
+ kore_mem_free(sdup);
return (t);
}
diff --git a/src/worker.c b/src/worker.c
@@ -47,6 +47,8 @@
#include "kore.h"
#include "http.h"
+//#define WORKER_DEBUG 1
+
#if defined(WORKER_DEBUG)
#define worker_debug(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
@@ -55,7 +57,7 @@
#define KORE_SHM_KEY 15000
#define WORKER(id) \
- (struct kore_worker *)kore_workers + (sizeof(struct kore_worker) * id)
+ (struct kore_worker *)(kore_workers + (sizeof(struct kore_worker) * id))
struct wlock {
pid_t lock;
@@ -75,9 +77,7 @@ static TAILQ_HEAD(, connection) disconnected;
static TAILQ_HEAD(, connection) worker_clients;
static struct kore_worker *kore_workers;
static int shm_accept_key;
-
-static struct wlock *accept_lock;
-static u_int8_t worker_has_acceptlock = 0;
+static struct wlock *accept_lock;
extern volatile sig_atomic_t sig_recv;
struct kore_worker *worker = NULL;
@@ -130,7 +130,9 @@ kore_worker_spawn(u_int16_t id, u_int16_t cpu)
kw->id = id;
kw->cpu = cpu;
kw->load = 0;
+ kw->accepted = 0;
kw->pid = fork();
+
if (kw->pid == -1)
fatal("could not spawn worker child: %s", errno_s);
@@ -217,7 +219,9 @@ kore_worker_entry(struct kore_worker *kw)
kore_platform_event_init();
kore_accesslog_worker_init();
+ worker->accept_treshold = worker_max_connections / 10;
kore_log(LOG_NOTICE, "worker %d started (cpu#%d)", kw->id, kw->cpu);
+
for (;;) {
if (sig_recv != 0) {
if (sig_recv == SIGHUP)
@@ -227,11 +231,19 @@ kore_worker_entry(struct kore_worker *kw)
sig_recv = 0;
}
- if (!worker_has_acceptlock &&
- worker_active_connections < worker_max_connections)
+ if (!worker->has_lock)
kore_worker_acceptlock_obtain();
- if (kore_platform_event_wait() && worker_has_acceptlock)
+
+ kore_platform_event_wait();
+
+ if (worker->accepted >= worker->accept_treshold &&
+ worker->has_lock) {
+ worker->accepted = 0;
kore_worker_acceptlock_release();
+ }
+
+ printf("%d: %d conn / %d mem\n", worker->id,
+ worker_active_connections, meminuse);
http_process();
@@ -325,6 +337,10 @@ kore_worker_wait(int final)
"worker %d (pid: %d) gone, respawning new one",
kw->id, kw->pid);
kore_worker_spawn(kw->id, kw->cpu);
+ } else {
+ kore_log(LOG_NOTICE,
+ "worker %d (pid: %d) signaled us",
+ kw->id, kw->pid);
}
break;
@@ -334,17 +350,15 @@ kore_worker_wait(int final)
static void
kore_worker_acceptlock_obtain(void)
{
- if (worker_count == 1 && !worker_has_acceptlock) {
- worker_has_acceptlock = 1;
+ if (worker_count == 1 && !worker->has_lock) {
+ worker->has_lock = 1;
kore_platform_enable_accept();
return;
}
if (worker_trylock()) {
- worker_has_acceptlock = 1;
+ worker->has_lock = 1;
kore_platform_enable_accept();
- worker_debug("%d: obtained accept lock (%d/%d)\n", worker->id,
- worker_active_connections, worker_max_connections);
}
}
@@ -354,17 +368,15 @@ kore_worker_acceptlock_release(void)
if (worker_count == 1)
return;
- if (worker_has_acceptlock != 1) {
+ if (worker->has_lock != 1) {
kore_log(LOG_NOTICE,
"kore_worker_acceptlock_release() != 1");
return;
}
if (worker_unlock()) {
- worker_has_acceptlock = 0;
+ worker->has_lock = 0;
kore_platform_disable_accept();
- worker_debug("%d: released %d/%d\n", worker->id,
- worker_active_connections, worker_max_connections);
}
}
@@ -375,6 +387,8 @@ worker_trylock(void)
worker->id, worker->pid) != worker->id)
return (0);
+ worker_debug("wrk#%d grabbed lock (%d/%d)\n", worker->id,
+ worker_active_connections, worker_max_connections);
worker_decide_next();
return (1);
@@ -383,12 +397,8 @@ worker_trylock(void)
static int
worker_unlock(void)
{
- if (accept_lock->next == worker->id) {
- worker_debug("%d: retaining lock\n", worker->id);
- worker_decide_next();
- return (0);
- }
-
+ worker_debug("%d: wrk#%d releasing (%d/%d)\n", worker->id, worker->id,
+ worker_active_connections, worker_max_connections);
if (__sync_val_compare_and_swap(&(accept_lock->lock),
accept_lock->current, accept_lock->next) != accept_lock->current)
kore_log(LOG_NOTICE, "kore_internal_unlock(): wasnt locked");
@@ -399,25 +409,14 @@ worker_unlock(void)
static void
worker_decide_next(void)
{
- u_int16_t id, load;
- struct kore_worker *kw, *low;
-
- low = NULL;
- load = worker_max_connections;
- for (id = 0; id < worker_count; id++) {
- kw = WORKER(id);
- if (kw->load < load) {
- load = kw->load;
- low = kw;
- }
- }
+ struct kore_worker *kw;
- if (low == NULL) {
- low = WORKER(accept_lock->workerid++);
- if (accept_lock->workerid == worker_count)
- accept_lock->workerid = 0;
- }
+ kw = WORKER(accept_lock->workerid++);
+ worker_debug("%d: next wrk#%d (%d, %p)\n",
+ worker->id, kw->id, kw->pid, kw);
+ if (accept_lock->workerid == worker_count)
+ accept_lock->workerid = 0;
- accept_lock->next = low->id;
+ accept_lock->next = kw->id;
accept_lock->current = worker->pid;
}