Remove most memory leaks with valgrind
This commit is contained in:
2
Makefile
2
Makefile
@ -36,7 +36,7 @@ bin/res:
|
|||||||
mkdir -p bin/res
|
mkdir -p bin/res
|
||||||
|
|
||||||
bin/test: test/mock_*.c test/test_*.c \
|
bin/test: test/mock_*.c test/test_*.c \
|
||||||
src/lib/utils.c src/lib/sock.c src/lib/list.c src/lib/http.c src/lib/http_static.c src/logger.c
|
src/lib/utils.c src/lib/sock.c src/lib/list.c src/lib/http.c src/lib/http_static.c src/logger.c src/lib/error.c
|
||||||
$(CC) -o $@ $(CFLAGS) $^ -lcriterion
|
$(CC) -o $@ $(CFLAGS) $^ -lcriterion
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,6 +69,9 @@ int compress_free(compress_ctx *ctx) {
|
|||||||
BrotliEncoderDestroyInstance(ctx->brotli);
|
BrotliEncoderDestroyInstance(ctx->brotli);
|
||||||
ctx->brotli = NULL;
|
ctx->brotli = NULL;
|
||||||
}
|
}
|
||||||
|
if (ctx->mode & COMPRESS_GZ) {
|
||||||
|
deflateEnd(&ctx->gzip);
|
||||||
|
}
|
||||||
ctx->mode = 0;
|
ctx->mode = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ int config_load(const char *filename) {
|
|||||||
if (comment != NULL) comment[0] = 0;
|
if (comment != NULL) comment[0] = 0;
|
||||||
|
|
||||||
unsigned long len = strlen(ptr);
|
unsigned long len = strlen(ptr);
|
||||||
char *end_ptr = ptr + len - 1;
|
char *end_ptr = (len > 0) ? ptr + len - 1 : ptr;
|
||||||
while (end_ptr[0] == ' ' || end_ptr[0] == '\t') {
|
while (end_ptr[0] == ' ' || end_ptr[0] == '\t') {
|
||||||
end_ptr[0] = 0;
|
end_ptr[0] = 0;
|
||||||
end_ptr--;
|
end_ptr--;
|
||||||
@ -161,6 +161,8 @@ int config_load(const char *filename) {
|
|||||||
if (strlen(source) == 0) {
|
if (strlen(source) == 0) {
|
||||||
err:
|
err:
|
||||||
critical("Unable to parse config file (line %i)", line);
|
critical("Unable to parse config file (line %i)", line);
|
||||||
|
free(line);
|
||||||
|
fclose(file);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +184,7 @@ int config_load(const char *filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
for (int k = 0; k < i; k++) {
|
for (int k = 0; k < i; k++) {
|
||||||
host_config_t *hc = &config.hosts[k];
|
host_config_t *hc = &config.hosts[k];
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define FACTOR 4
|
#define FACTOR 4
|
||||||
|
#define meta(ptr) ((list_meta_t *) ((unsigned char *) (ptr) - sizeof(list_meta_t)))
|
||||||
|
#define data(ptr) ((unsigned char *) (ptr) + sizeof(list_meta_t))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int init_size, elem_size, max_size, size;
|
int init_size, elem_size, max_size, size;
|
||||||
@ -30,21 +32,24 @@ void *list_create(int elem_size, int init_elem_n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *list_ptr = malloc(sizeof(list_meta_t) + elem_size * init_elem_n);
|
void *list_ptr = malloc(sizeof(list_meta_t) + elem_size * init_elem_n);
|
||||||
|
if (list_ptr == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(list_ptr, 0, sizeof(list_meta_t) + elem_size * init_elem_n);
|
||||||
list_meta_t *list = list_ptr;
|
list_meta_t *list = list_ptr;
|
||||||
list->init_size = init_elem_n;
|
list->init_size = init_elem_n;
|
||||||
list->elem_size = elem_size;
|
list->elem_size = elem_size;
|
||||||
list->max_size = init_elem_n;
|
list->max_size = init_elem_n;
|
||||||
list->size = 0;
|
list->size = 0;
|
||||||
return (unsigned char *) list_ptr + sizeof(list_meta_t);
|
return data(list_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int list_size(const void *list_ptr) {
|
int list_size(const void *list_ptr) {
|
||||||
list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t));
|
return meta(list_ptr)->size;
|
||||||
return list->size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int list_find(void *list_ptr, void *elem) {
|
int list_find(void *list_ptr, void *elem) {
|
||||||
list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t));
|
list_meta_t *list = meta(list_ptr);
|
||||||
unsigned char *array = list_ptr;
|
unsigned char *array = list_ptr;
|
||||||
|
|
||||||
for (int i = 0; i < list->size; i++) {
|
for (int i = 0; i < list->size; i++) {
|
||||||
@ -60,32 +65,31 @@ void *list_insert(void *list_ptr, void *elem, int n) {
|
|||||||
void *ptr = NULL;
|
void *ptr = NULL;
|
||||||
list_ptr = list_insert_ptr(list_ptr, &ptr, n);
|
list_ptr = list_insert_ptr(list_ptr, &ptr, n);
|
||||||
if (list_ptr != NULL && ptr != NULL) {
|
if (list_ptr != NULL && ptr != NULL) {
|
||||||
list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t));
|
memcpy(ptr, elem, meta(list_ptr)->elem_size);
|
||||||
memcpy(ptr, elem, list->elem_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return list_ptr;
|
return list_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *list_insert_ptr(void *list_ptr, void **elem, int n) {
|
void *list_insert_ptr(void *list_ptr, void **elem, int n) {
|
||||||
list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t));
|
list_meta_t *list = meta(list_ptr);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
n = list->size + n + 1;
|
n = list->size + n + 1;
|
||||||
|
|
||||||
if (list->size >= list->max_size) {
|
if (list->size >= list->max_size) {
|
||||||
if ((list = list_resize(list, list->max_size * FACTOR)) == NULL) {
|
if ((list = list_resize(list, list->max_size * FACTOR)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *array = (unsigned char *) list + sizeof(list_meta_t);
|
unsigned char *array = data(list);
|
||||||
|
|
||||||
if (n < list->size)
|
if (n < list->size)
|
||||||
memmove(array + (n + 1) * list->elem_size, array + n * list->elem_size, (list->size - n) * list->elem_size);
|
memmove(array + (n + 1) * list->elem_size, array + n * list->elem_size, (list->size - n) * list->elem_size);
|
||||||
*elem = array + n * list->elem_size;
|
*elem = array + n * list->elem_size;
|
||||||
|
memset(*elem, 0, list->elem_size);
|
||||||
|
|
||||||
list->size++;
|
list->size++;
|
||||||
return (unsigned char *) list + sizeof(list_meta_t);
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *list_append(void *list_ptr, void *elem) {
|
void *list_append(void *list_ptr, void *elem) {
|
||||||
@ -97,7 +101,7 @@ void *list_append_ptr(void *list_ptr, void **elem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *list_remove(void *list_ptr, int n) {
|
void *list_remove(void *list_ptr, int n) {
|
||||||
list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t));
|
list_meta_t *list = meta(list_ptr);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
n = list->size + n;
|
n = list->size + n;
|
||||||
|
|
||||||
@ -106,6 +110,8 @@ void *list_remove(void *list_ptr, int n) {
|
|||||||
if (list->size > 1 && n < list->size)
|
if (list->size > 1 && n < list->size)
|
||||||
memmove(array + n * list->elem_size, array + (n + 1) * list->elem_size, (list->size - n - 1) * list->elem_size);
|
memmove(array + n * list->elem_size, array + (n + 1) * list->elem_size, (list->size - n - 1) * list->elem_size);
|
||||||
|
|
||||||
|
memset(array + list->size * list->elem_size, 0, list->elem_size);
|
||||||
|
|
||||||
list->size--;
|
list->size--;
|
||||||
if (list->size < list->max_size / FACTOR / 2 && list->max_size / FACTOR >= list->init_size) {
|
if (list->size < list->max_size / FACTOR / 2 && list->max_size / FACTOR >= list->init_size) {
|
||||||
if ((list = list_resize(list, list->max_size / FACTOR)) == NULL) {
|
if ((list = list_resize(list, list->max_size / FACTOR)) == NULL) {
|
||||||
@ -113,7 +119,7 @@ void *list_remove(void *list_ptr, int n) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (unsigned char *) list + sizeof(list_meta_t);
|
return data(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *list_delete(void *list_ptr, void *elem) {
|
void *list_delete(void *list_ptr, void *elem) {
|
||||||
@ -126,14 +132,13 @@ void *list_delete(void *list_ptr, void *elem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *list_clear(void *list_ptr) {
|
void *list_clear(void *list_ptr) {
|
||||||
list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t));
|
list_meta_t *list = meta(list_ptr);
|
||||||
list->size = 0;
|
list->size = 0;
|
||||||
memset(list_ptr, 0, list->max_size * list->elem_size);
|
memset(list_ptr, 0, list->max_size * list->elem_size);
|
||||||
list->max_size = list->init_size;
|
list->max_size = list->init_size;
|
||||||
return (unsigned char *) list_resize(list, list->max_size * list->elem_size) + sizeof(list_meta_t);
|
return data(list_resize(list, list->max_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_free(void *list_ptr) {
|
void list_free(void *list_ptr) {
|
||||||
list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t));
|
free(meta(list_ptr));
|
||||||
free(list);
|
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sock_recv(&proxy->proxy, buffer, sizeof(buffer), MSG_PEEK);
|
ret = sock_recv(&proxy->proxy, buffer, sizeof(buffer) - 1, MSG_PEEK);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
int e_sys = error_get_sys(), e_ssl = error_get_ssl();
|
int e_sys = error_get_sys(), e_ssl = error_get_ssl();
|
||||||
if (e_sys == EAGAIN || e_sys == EINPROGRESS || e_ssl == SSL_ERROR_WANT_READ || e_ssl == SSL_ERROR_WANT_WRITE) {
|
if (e_sys == EAGAIN || e_sys == EINPROGRESS || e_ssl == SSL_ERROR_WANT_READ || e_ssl == SSL_ERROR_WANT_WRITE) {
|
||||||
@ -477,6 +477,7 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
|
|||||||
retry = tries < 4;
|
retry = tries < 4;
|
||||||
goto proxy_err;
|
goto proxy_err;
|
||||||
}
|
}
|
||||||
|
buffer[ret] = 0;
|
||||||
|
|
||||||
char *buf = buffer;
|
char *buf = buffer;
|
||||||
unsigned short header_len = (unsigned short) (strstr(buffer, "\r\n\r\n") - buffer + 4);
|
unsigned short header_len = (unsigned short) (strstr(buffer, "\r\n\r\n") - buffer + 4);
|
||||||
|
56
src/server.c
56
src/server.c
@ -79,15 +79,18 @@ static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void server_free_client(client_ctx_t *ctx) {
|
void server_free_client(client_ctx_t *ctx) {
|
||||||
for (int i = 0; i < list_size(clients); i++) {
|
clients = list_delete(clients, &ctx);
|
||||||
if (clients[i] == ctx) {
|
|
||||||
clients = list_remove(clients, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ssl_free() {
|
||||||
|
for (int i = 0; i < CONFIG_MAX_CERT_CONFIG; i++) {
|
||||||
|
const cert_config_t *conf = &config.certs[i];
|
||||||
|
if (conf->name[0] == 0) break;
|
||||||
|
SSL_CTX_free(contexts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void accept_cb(void *arg) {
|
static void accept_cb(void *arg) {
|
||||||
int i = (int) (((int *) arg) - sockets);
|
int i = (int) (((int *) arg) - sockets);
|
||||||
int fd = sockets[i];
|
int fd = sockets[i];
|
||||||
@ -98,14 +101,6 @@ static void accept_cb(void *arg) {
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clients = list_append(clients, &client_ctx);
|
|
||||||
if (clients == NULL) {
|
|
||||||
critical("Unable to add client context to list");
|
|
||||||
errno = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_ctx->in_use = 1;
|
client_ctx->in_use = 1;
|
||||||
sock *client = &client_ctx->socket;
|
sock *client = &client_ctx->socket;
|
||||||
|
|
||||||
@ -124,6 +119,13 @@ static void accept_cb(void *arg) {
|
|||||||
client_ctx->cnx_s = client->ts_start;
|
client_ctx->cnx_s = client->ts_start;
|
||||||
client_ctx->cnx_e = -1, client_ctx->req_s = -1, client_ctx->req_e = -1, client_ctx->res_ts = -1;
|
client_ctx->cnx_e = -1, client_ctx->req_s = -1, client_ctx->req_e = -1, client_ctx->res_ts = -1;
|
||||||
|
|
||||||
|
clients = list_append(clients, &client_ctx);
|
||||||
|
if (clients == NULL) {
|
||||||
|
critical("Unable to add client context to list");
|
||||||
|
errno = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tcp_accept(client_ctx);
|
tcp_accept(client_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,9 +162,9 @@ static void terminate_gracefully(int sig) {
|
|||||||
workers_stop();
|
workers_stop();
|
||||||
workers_destroy();
|
workers_destroy();
|
||||||
|
|
||||||
for (int i = 0; i < list_size(clients); i++) {
|
while (list_size(clients) > 0)
|
||||||
tcp_close(clients[i]);
|
server_free_client(clients[0]);
|
||||||
}
|
|
||||||
proxy_close_all();
|
proxy_close_all();
|
||||||
logger_set_prefix("");
|
logger_set_prefix("");
|
||||||
|
|
||||||
@ -177,11 +179,6 @@ int main(int argc, char *const argv[]) {
|
|||||||
int mode = 0;
|
int mode = 0;
|
||||||
|
|
||||||
memset(sockets, 0, sizeof(sockets));
|
memset(sockets, 0, sizeof(sockets));
|
||||||
clients = list_create(sizeof(void *), 64);
|
|
||||||
if (clients == NULL) {
|
|
||||||
critical("Unable to initialize client list");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct sockaddr_in6 addresses[2] = {
|
const struct sockaddr_in6 addresses[2] = {
|
||||||
{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(80)},
|
{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(80)},
|
||||||
@ -309,15 +306,26 @@ int main(int argc, char *const argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clients = list_create(sizeof(client_ctx_t *), 64);
|
||||||
|
if (clients == NULL) {
|
||||||
|
critical("Unable to initialize client list");
|
||||||
|
ssl_free();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (async_init() != 0) {
|
if (async_init() != 0) {
|
||||||
critical("Unable to initialize async thread");
|
critical("Unable to initialize async thread");
|
||||||
|
ssl_free();
|
||||||
geoip_free();
|
geoip_free();
|
||||||
|
list_free(clients);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy_preload() != 0) {
|
if (proxy_preload() != 0) {
|
||||||
critical("Unable to initialize proxy");
|
critical("Unable to initialize proxy");
|
||||||
|
ssl_free();
|
||||||
geoip_free();
|
geoip_free();
|
||||||
|
list_free(clients);
|
||||||
async_free();
|
async_free();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -325,7 +333,10 @@ int main(int argc, char *const argv[]) {
|
|||||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||||
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
||||||
critical("Unable to listen on socket %i", i);
|
critical("Unable to listen on socket %i", i);
|
||||||
|
ssl_free();
|
||||||
geoip_free();
|
geoip_free();
|
||||||
|
list_free(clients);
|
||||||
|
async_free();
|
||||||
proxy_unload();
|
proxy_unload();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -347,6 +358,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
notice("Goodbye!");
|
notice("Goodbye!");
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
|
ssl_free();
|
||||||
list_free(clients);
|
list_free(clients);
|
||||||
geoip_free();
|
geoip_free();
|
||||||
proxy_unload();
|
proxy_unload();
|
||||||
|
@ -29,12 +29,14 @@ void proxy_handler_func(client_ctx_t *ctx) {
|
|||||||
|
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
proxy_unlock_ctx(ctx->proxy);
|
proxy_unlock_ctx(ctx->proxy);
|
||||||
|
ctx->proxy->client = NULL;
|
||||||
ctx->proxy = NULL;
|
ctx->proxy = NULL;
|
||||||
} else if (ctx->use_proxy == 0) {
|
} else if (ctx->use_proxy == 0) {
|
||||||
proxy_close(ctx->proxy);
|
proxy_close(ctx->proxy);
|
||||||
} else if (ctx->use_proxy == 1) {
|
} else if (ctx->use_proxy == 1) {
|
||||||
proxy_handler_2(ctx);
|
proxy_handler_2(ctx);
|
||||||
proxy_unlock_ctx(ctx->proxy);
|
proxy_unlock_ctx(ctx->proxy);
|
||||||
|
ctx->proxy->client = NULL;
|
||||||
ctx->proxy = NULL;
|
ctx->proxy = NULL;
|
||||||
} else if (ctx->use_proxy == 2) {
|
} else if (ctx->use_proxy == 2) {
|
||||||
// WebSocket
|
// WebSocket
|
||||||
|
Reference in New Issue
Block a user