From 5ee77b4628e56e261e71e537b8a352855ab1dfc1 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Sun, 22 Jun 2025 15:32:13 +0200 Subject: [PATCH] Protect global data with locks --- baked.c | 34 +++++++++++++----- baked.h | 2 ++ locked.h | 12 +++++++ main.c | 49 ++++++++++++++------------ routes.c | 105 ++++++------------------------------------------------- routes.h | 16 +++------ timer.c | 11 ++++-- 7 files changed, 90 insertions(+), 139 deletions(-) create mode 100644 locked.h diff --git a/baked.c b/baked.c index e6e0679..8e1b625 100644 --- a/baked.c +++ b/baked.c @@ -5,6 +5,7 @@ #include "stb/stb_ds.h" #include "baked.h" +#include "locked.h" INCBIN(gpp1, "./gpp1"); @@ -24,7 +25,17 @@ INCBIN(blog_welcome_md, "./blog/welcome.md"); INCBIN(blog_weird_page_md, "./blog/weird-page.md"); INCBIN(blog_curious_case_of_gebs_md, "./blog/curious-case-of-gebs.md"); -Baked_Resource *baked_resources = NULL; +locked(Baked_Resource *) baked_resources = locked_init(nil); + +void lock_baked_resources(void) +{ + lockx(&baked_resources); +} + +void unlock_baked_resources(void) +{ + unlockx(&baked_resources); +} void add_baked_resource(char *key, const uchar *data, size_t size) { @@ -34,11 +45,12 @@ void add_baked_resource(char *key, const uchar *data, size_t size) abort(); } write(fd, data, size); - shput(baked_resources, key, fd); + shput(baked_resources.value, key, fd); } void init_baked_resources(void) { + lockx(&baked_resources); add_baked_resource("home.html", home_html_data, home_html_size); add_baked_resource("page-missing.html", page_missing_html_data, page_missing_html_size); add_baked_resource("template-blog.html", template_blog_html_data, template_blog_html_size); @@ -53,21 +65,25 @@ void init_baked_resources(void) add_baked_resource("blog-welcome.md", blog_welcome_md_data, blog_welcome_md_size); add_baked_resource("blog-weird-page.md", blog_weird_page_md_data, blog_weird_page_md_size); add_baked_resource("blog-curious-case-of-gebs.md", blog_curious_case_of_gebs_md_data, blog_curious_case_of_gebs_md_size); + unlockx(&baked_resources); } void free_baked_resources(void) { - for (size_t i = 0; i < shlen(baked_resources); i++) { - close(baked_resources[i].value); + lockx(&baked_resources); + for (size_t i = 0; i < shlen(baked_resources.value); i++) { + close(baked_resources.value[i].value); } - shfree(baked_resources); + shfree(baked_resources.value); + unlockx(&baked_resources); } bool get_baked_resource_path(char *key, char *buf, size_t size) { - if (shgeti(baked_resources, key) != -1) { - int fd = shget(baked_resources, key); + if (shgeti(baked_resources.value, key) != -1) { + int fd = shget(baked_resources.value, key); snprintf(buf, size, "/proc/%d/fd/%d", getpid(), fd); + unlockx(&baked_resources); return true; } return false; @@ -75,8 +91,8 @@ bool get_baked_resource_path(char *key, char *buf, size_t size) void baked_resource_each(void (*f)(Baked_Resource *resource, void *udata), void *udata) { - for (size_t i = 0; i < shlen(baked_resources); i++) { - f(&baked_resources[i], udata); + for (size_t i = 0; i < shlen(baked_resources.value); i++) { + f(&baked_resources.value[i], udata); } } diff --git a/baked.h b/baked.h index e33870d..8ef3b98 100644 --- a/baked.h +++ b/baked.h @@ -30,5 +30,7 @@ void init_baked_resources(void); void free_baked_resources(void); bool get_baked_resource_path(char *key, char *buf, size_t size); void baked_resource_each(void (*f)(Baked_Resource *resource, void *udata), void *udata); +void lock_baked_resources(void); +void unlock_baked_resources(void); #endif // BAKED_H_ diff --git a/locked.h b/locked.h new file mode 100644 index 0000000..5e892a7 --- /dev/null +++ b/locked.h @@ -0,0 +1,12 @@ +#ifndef LOCKED_H_ +#define LOCKED_H_ + +#include + +#define locked_init(x) { .value = (x), .lock = PTHREAD_MUTEX_INITIALIZER } +#define locked(T) struct { T value; pthread_mutex_t lock; } + +#define lockx(x) pthread_mutex_lock(&(x)->lock) +#define unlockx(x) pthread_mutex_unlock(&(x)->lock) + +#endif // LOCKED_H_ diff --git a/main.c b/main.c index 898908a..922e5d4 100644 --- a/main.c +++ b/main.c @@ -15,13 +15,10 @@ #include "timer.h" #include "CONFIG.h" #include "clonestr.h" +#include "locked.h" -Route *route_hashtable = nil; -/* char *etc_dump_path = nil; */ -struct { char *value; pthread_mutex_t lock; } etc_dump_path = { - .value = nil, - .lock = PTHREAD_MUTEX_INITIALIZER, -}; +locked(Route *) route_hashtable = locked_init(nil); +locked(char *) etc_dump_path = locked_init(nil); void run_in_thread(void *(*f)(void *), void *p) { @@ -63,9 +60,9 @@ void *route_thread_function(void *param) char *file = basename(p); char *full_path = malloc(PATH_MAX); - pthread_mutex_lock(&etc_dump_path.lock); + lockx(&etc_dump_path); snprintf(full_path, PATH_MAX, "%s/%s", etc_dump_path.value, file); - pthread_mutex_unlock(&etc_dump_path.lock); + unlockx(&etc_dump_path); sb_append_nstr(&result.body, full_path); sb_finish(&result.body); @@ -79,10 +76,12 @@ void *route_thread_function(void *param) char key[MG_PATH_MAX] = {0}; strncpy(key, http_msg.uri.buf, http_msg.uri.len); - ssize_t idx = shgeti(route_hashtable, key); + lockx(&route_hashtable); + ssize_t idx = shgeti(route_hashtable.value, key); Route_Result result = {0}; - route_hashtable[idx].value(&http_msg, &result, route_hashtable[idx].context_data); + route_hashtable.value[idx].value(&http_msg, &result, route_hashtable.value[idx].context_data); + unlockx(&route_hashtable); mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result)); free(data->message.buf); @@ -136,27 +135,31 @@ void route_hashtable_put_blogs(Baked_Resource *resource, void *udata) && strncmp(resource->key, "blog-", strlen("blog-")) == 0) { char path[MG_PATH_MAX]; snprintf(path, MG_PATH_MAX, "/%s", resource->key); - shput(route_hashtable, path, &route_generic_blog); - route_hashtable[shgeti(route_hashtable, path)].context_data = (void *)resource; + shput(route_hashtable.value, path, &route_generic_blog); + route_hashtable.value[shgeti(route_hashtable.value, path)].context_data = (void *)resource; } } void init_route_hashtable(void) { - shdefault(route_hashtable, &route_page_not_found); - shput(route_hashtable, "/", &route_home); - shput(route_hashtable, "/page-missing", &route_page_not_found); - shput(route_hashtable, "/blog", &route_blog); + lockx(&route_hashtable); + shdefault(route_hashtable.value, &route_page_not_found); + shput(route_hashtable.value, "/", &route_home); + shput(route_hashtable.value, "/page-missing", &route_page_not_found); + shput(route_hashtable.value, "/blog", &route_blog); #if MY_DEBUG - shput(route_hashtable, "/build-id", &route_build_id); + shput(route_hashtable.value, "/build-id", &route_build_id); #endif baked_resource_each(&route_hashtable_put_blogs, nil); + unlockx(&route_hashtable); } void free_route_hashtable(void) { - shfree(route_hashtable); + lockx(&route_hashtable); + shfree(route_hashtable.value); + unlockx(&route_hashtable); } char *init_etc_dump(void) @@ -235,6 +238,7 @@ void populate_etc_dump(char *etc_dump) "simple.css", "me.jpg", }; + lock_baked_resources(); for (size_t i = 0; i < sizeof(files)/sizeof(files[0]); i++) { char path[PATH_MAX]; get_baked_resource_path(files[i], path, sizeof(path)); @@ -242,6 +246,7 @@ void populate_etc_dump(char *etc_dump) snprintf(dest, sizeof(dest), "%s/%s", etc_dump, files[i]); cp(path, dest); } + unlock_baked_resources(); } volatile bool alive = true; @@ -254,12 +259,12 @@ int main(int argc, char ** argv) start_timer(); init_baked_resources(); - pthread_mutex_lock(&etc_dump_path.lock); + lockx(&etc_dump_path); if ((etc_dump_path.value = init_etc_dump()) == nil) { return 1; } populate_etc_dump(etc_dump_path.value); - pthread_mutex_unlock(&etc_dump_path.lock); + unlockx(&etc_dump_path); mg_log_set(MG_LL_DEBUG); struct mg_mgr mgr; @@ -277,9 +282,9 @@ int main(int argc, char ** argv) mg_mgr_free(&mgr); - pthread_mutex_lock(&etc_dump_path.lock); + lockx(&etc_dump_path); free_etc_dump(etc_dump_path.value); - pthread_mutex_unlock(&etc_dump_path.lock); + unlockx(&etc_dump_path); free_baked_resources(); return 0; diff --git a/routes.c b/routes.c index 21e70b0..2153311 100644 --- a/routes.c +++ b/routes.c @@ -34,19 +34,6 @@ void make_application_json(Route_Result *result, int code, cJSON *root) sb_finish(&result->body); } -void make_binary(Route_Result *result, char *content_type, int code, char *data, size_t size) -{ - char type[100]; - snprintf(type, sizeof(type), "Content-Type: %s", content_type); - result->status_code = code; - result->type = ROUTE_RESULT_DYNAMIC; - list_append(&result->headers, clonestr(type)); - for (size_t i = 0; i < size; i++) { - sb_append_char(&result->body, data[i]); - } - sb_finish(&result->body); -} - void make_text(Route_Result *result, char *subtype, int code, char *in) { char type[100]; @@ -83,7 +70,7 @@ bool gpp_run(char *path, NString_List *env, String_Builder *out) } #if MY_DEBUG -ROUTE_HANDLER(build_id) +void route_build_id(struct mg_http_message *msg, Route_Result *result, void *context_data) { cJSON *root = cJSON_CreateObject(); defer { cJSON_Delete(root); } @@ -104,8 +91,10 @@ ROUTE_HANDLER(build_id) } #endif -ROUTE_HANDLER(page_not_found) +void route_page_not_found(struct mg_http_message *msg, Route_Result *result, void *context_data) { + lock_baked_resources(); + defer { unlock_baked_resources(); } NString_List env = {0}; defer { list_free(&env); } @@ -139,84 +128,10 @@ ROUTE_HANDLER(page_not_found) } } -ROUTE_HANDLER(simple_css) -{ - char path[PATH_MAX] = {0}; - if (!get_baked_resource_path("simple.css", path, sizeof(path))) { - make_internal_server_error(result); - return; - } - - String_Builder sb = {0}; - defer { sb_free(&sb); } - if (!sb_read_file(&sb, path)) { - make_internal_server_error(result); - return; - } - sb_finish(&sb); - - make_text(result, "css", 200, sb.items); -} - -ROUTE_HANDLER(me_jpg) -{ - char path[PATH_MAX] = {0}; - if (!get_baked_resource_path("me.jpg", path, sizeof(path))) { - make_internal_server_error(result); - return; - } - - String_Builder sb = {0}; - defer { sb_free(&sb); } - if (!sb_read_file(&sb, path)) { - make_internal_server_error(result); - return; - } - - make_binary(result, "image/jpeg", 200, sb.items, sb.count); -} - -ROUTE_HANDLER(favicon) -{ - char path[PATH_MAX] = {0}; - if (!get_baked_resource_path("favicon.ico", path, sizeof(path))) { - make_internal_server_error(result); - return; - } - - String_Builder sb = {0}; - defer { sb_free(&sb); } - if (!sb_read_file(&sb, path)) { - make_internal_server_error(result); - return; - } - - make_binary(result, "image/x-icon", 200, sb.items, sb.count); -} - -#if MY_DEBUG -ROUTE_HANDLER(hotreload_js) -{ - char path[PATH_MAX] = {0}; - if (!get_baked_resource_path("hotreload.js", path, sizeof(path))) { - make_internal_server_error(result); - return; - } - - String_Builder sb = {0}; - defer { sb_free(&sb); } - if (!sb_read_file(&sb, path)) { - make_internal_server_error(result); - return; - } - sb_finish(&sb); - - make_text(result, "javascript", 200, sb.items); -} -#endif - -ROUTE_HANDLER(home) +void route_home(struct mg_http_message *msg, Route_Result *result, void *context_data) { + lock_baked_resources(); + defer { unlock_baked_resources(); } NString_List env = {0}; defer { list_free(&env); } @@ -248,8 +163,10 @@ ROUTE_HANDLER(home) } } -ROUTE_HANDLER(generic_blog) +void route_generic_blog(struct mg_http_message *msg, Route_Result *result, void *context_data) { + lock_baked_resources(); + defer { unlock_baked_resources(); } NString_List env = {0}; defer { list_free(&env); } @@ -332,7 +249,7 @@ void collect_blogs(Baked_Resource *resource, void *udata) } } -ROUTE_HANDLER(blog) +void route_blog(struct mg_http_message *msg, Route_Result *result, void *context_data) { NString_List env = {0}; defer { list_free(&env); } diff --git a/routes.h b/routes.h index 6a1dd50..55d8b9d 100644 --- a/routes.h +++ b/routes.h @@ -28,18 +28,12 @@ typedef struct { void *context_data; } Route; -#define ROUTE_HANDLER(name) void route_##name(struct mg_http_message *msg, Route_Result *result, void *context_data) - -ROUTE_HANDLER(page_not_found); -ROUTE_HANDLER(simple_css); -ROUTE_HANDLER(favicon); -ROUTE_HANDLER(me_jpg); #if MY_DEBUG -ROUTE_HANDLER(hotreload_js); -ROUTE_HANDLER(build_id); +void route_build_id(struct mg_http_message *msg, Route_Result *result, void *context_data); #endif -ROUTE_HANDLER(home); -ROUTE_HANDLER(generic_blog); -ROUTE_HANDLER(blog); +void route_page_not_found(struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_home(struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_generic_blog(struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_blog(struct mg_http_message *msg, Route_Result *result, void *context_data); #endif // ROUTES_H_ diff --git a/timer.c b/timer.c index f73a872..c45f528 100644 --- a/timer.c +++ b/timer.c @@ -3,22 +3,27 @@ #include #include "timer.h" +#include "locked.h" -time_t rawtime; +locked(time_t) rawtime; void start_timer(void) { - time(&rawtime); + lockx(&rawtime); + time(&rawtime.value); + unlockx(&rawtime); } void get_timer_string(char *output, size_t size) { + lockx(&rawtime); struct tm * timeinfo; - timeinfo = localtime(&rawtime); + timeinfo = localtime(&rawtime.value); snprintf(output, size, "[%02d %02d %d %02d:%02d:%02d]", timeinfo->tm_mday, timeinfo->tm_mon + 1, timeinfo->tm_year + 1900, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + unlockx(&rawtime); }