Protect global data with locks

This commit is contained in:
kamkow1
2025-06-22 15:32:13 +02:00
parent a7f8ebea09
commit 5ee77b4628
7 changed files with 90 additions and 139 deletions

34
baked.c
View File

@ -5,6 +5,7 @@
#include "stb/stb_ds.h" #include "stb/stb_ds.h"
#include "baked.h" #include "baked.h"
#include "locked.h"
INCBIN(gpp1, "./gpp1"); 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_weird_page_md, "./blog/weird-page.md");
INCBIN(blog_curious_case_of_gebs_md, "./blog/curious-case-of-gebs.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) 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(); abort();
} }
write(fd, data, size); write(fd, data, size);
shput(baked_resources, key, fd); shput(baked_resources.value, key, fd);
} }
void init_baked_resources(void) void init_baked_resources(void)
{ {
lockx(&baked_resources);
add_baked_resource("home.html", home_html_data, home_html_size); 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("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); 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-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-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); 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) void free_baked_resources(void)
{ {
for (size_t i = 0; i < shlen(baked_resources); i++) { lockx(&baked_resources);
close(baked_resources[i].value); 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) bool get_baked_resource_path(char *key, char *buf, size_t size)
{ {
if (shgeti(baked_resources, key) != -1) { if (shgeti(baked_resources.value, key) != -1) {
int fd = shget(baked_resources, key); int fd = shget(baked_resources.value, key);
snprintf(buf, size, "/proc/%d/fd/%d", getpid(), fd); snprintf(buf, size, "/proc/%d/fd/%d", getpid(), fd);
unlockx(&baked_resources);
return true; return true;
} }
return false; 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) void baked_resource_each(void (*f)(Baked_Resource *resource, void *udata), void *udata)
{ {
for (size_t i = 0; i < shlen(baked_resources); i++) { for (size_t i = 0; i < shlen(baked_resources.value); i++) {
f(&baked_resources[i], udata); f(&baked_resources.value[i], udata);
} }
} }

View File

@ -30,5 +30,7 @@ void init_baked_resources(void);
void free_baked_resources(void); void free_baked_resources(void);
bool get_baked_resource_path(char *key, char *buf, size_t size); 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 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_ #endif // BAKED_H_

12
locked.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef LOCKED_H_
#define LOCKED_H_
#include <pthread.h>
#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_

49
main.c
View File

@ -15,13 +15,10 @@
#include "timer.h" #include "timer.h"
#include "CONFIG.h" #include "CONFIG.h"
#include "clonestr.h" #include "clonestr.h"
#include "locked.h"
Route *route_hashtable = nil; locked(Route *) route_hashtable = locked_init(nil);
/* char *etc_dump_path = nil; */ locked(char *) etc_dump_path = locked_init(nil);
struct { char *value; pthread_mutex_t lock; } etc_dump_path = {
.value = nil,
.lock = PTHREAD_MUTEX_INITIALIZER,
};
void run_in_thread(void *(*f)(void *), void *p) void run_in_thread(void *(*f)(void *), void *p)
{ {
@ -63,9 +60,9 @@ void *route_thread_function(void *param)
char *file = basename(p); char *file = basename(p);
char *full_path = malloc(PATH_MAX); 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); 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_append_nstr(&result.body, full_path);
sb_finish(&result.body); sb_finish(&result.body);
@ -79,10 +76,12 @@ void *route_thread_function(void *param)
char key[MG_PATH_MAX] = {0}; char key[MG_PATH_MAX] = {0};
strncpy(key, http_msg.uri.buf, http_msg.uri.len); 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_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)); mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result));
free(data->message.buf); 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) { && strncmp(resource->key, "blog-", strlen("blog-")) == 0) {
char path[MG_PATH_MAX]; char path[MG_PATH_MAX];
snprintf(path, MG_PATH_MAX, "/%s", resource->key); snprintf(path, MG_PATH_MAX, "/%s", resource->key);
shput(route_hashtable, path, &route_generic_blog); shput(route_hashtable.value, path, &route_generic_blog);
route_hashtable[shgeti(route_hashtable, path)].context_data = (void *)resource; route_hashtable.value[shgeti(route_hashtable.value, path)].context_data = (void *)resource;
} }
} }
void init_route_hashtable(void) void init_route_hashtable(void)
{ {
shdefault(route_hashtable, &route_page_not_found); lockx(&route_hashtable);
shput(route_hashtable, "/", &route_home); shdefault(route_hashtable.value, &route_page_not_found);
shput(route_hashtable, "/page-missing", &route_page_not_found); shput(route_hashtable.value, "/", &route_home);
shput(route_hashtable, "/blog", &route_blog); shput(route_hashtable.value, "/page-missing", &route_page_not_found);
shput(route_hashtable.value, "/blog", &route_blog);
#if MY_DEBUG #if MY_DEBUG
shput(route_hashtable, "/build-id", &route_build_id); shput(route_hashtable.value, "/build-id", &route_build_id);
#endif #endif
baked_resource_each(&route_hashtable_put_blogs, nil); baked_resource_each(&route_hashtable_put_blogs, nil);
unlockx(&route_hashtable);
} }
void free_route_hashtable(void) void free_route_hashtable(void)
{ {
shfree(route_hashtable); lockx(&route_hashtable);
shfree(route_hashtable.value);
unlockx(&route_hashtable);
} }
char *init_etc_dump(void) char *init_etc_dump(void)
@ -235,6 +238,7 @@ void populate_etc_dump(char *etc_dump)
"simple.css", "me.jpg", "simple.css", "me.jpg",
}; };
lock_baked_resources();
for (size_t i = 0; i < sizeof(files)/sizeof(files[0]); i++) { for (size_t i = 0; i < sizeof(files)/sizeof(files[0]); i++) {
char path[PATH_MAX]; char path[PATH_MAX];
get_baked_resource_path(files[i], path, sizeof(path)); 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]); snprintf(dest, sizeof(dest), "%s/%s", etc_dump, files[i]);
cp(path, dest); cp(path, dest);
} }
unlock_baked_resources();
} }
volatile bool alive = true; volatile bool alive = true;
@ -254,12 +259,12 @@ int main(int argc, char ** argv)
start_timer(); start_timer();
init_baked_resources(); init_baked_resources();
pthread_mutex_lock(&etc_dump_path.lock); lockx(&etc_dump_path);
if ((etc_dump_path.value = init_etc_dump()) == nil) { if ((etc_dump_path.value = init_etc_dump()) == nil) {
return 1; return 1;
} }
populate_etc_dump(etc_dump_path.value); populate_etc_dump(etc_dump_path.value);
pthread_mutex_unlock(&etc_dump_path.lock); unlockx(&etc_dump_path);
mg_log_set(MG_LL_DEBUG); mg_log_set(MG_LL_DEBUG);
struct mg_mgr mgr; struct mg_mgr mgr;
@ -277,9 +282,9 @@ int main(int argc, char ** argv)
mg_mgr_free(&mgr); mg_mgr_free(&mgr);
pthread_mutex_lock(&etc_dump_path.lock); lockx(&etc_dump_path);
free_etc_dump(etc_dump_path.value); free_etc_dump(etc_dump_path.value);
pthread_mutex_unlock(&etc_dump_path.lock); unlockx(&etc_dump_path);
free_baked_resources(); free_baked_resources();
return 0; return 0;

105
routes.c
View File

@ -34,19 +34,6 @@ void make_application_json(Route_Result *result, int code, cJSON *root)
sb_finish(&result->body); 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) void make_text(Route_Result *result, char *subtype, int code, char *in)
{ {
char type[100]; char type[100];
@ -83,7 +70,7 @@ bool gpp_run(char *path, NString_List *env, String_Builder *out)
} }
#if MY_DEBUG #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(); cJSON *root = cJSON_CreateObject();
defer { cJSON_Delete(root); } defer { cJSON_Delete(root); }
@ -104,8 +91,10 @@ ROUTE_HANDLER(build_id)
} }
#endif #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}; NString_List env = {0};
defer { list_free(&env); } defer { list_free(&env); }
@ -139,84 +128,10 @@ ROUTE_HANDLER(page_not_found)
} }
} }
ROUTE_HANDLER(simple_css) void route_home(struct mg_http_message *msg, Route_Result *result, void *context_data)
{
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)
{ {
lock_baked_resources();
defer { unlock_baked_resources(); }
NString_List env = {0}; NString_List env = {0};
defer { list_free(&env); } 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}; NString_List env = {0};
defer { list_free(&env); } 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}; NString_List env = {0};
defer { list_free(&env); } defer { list_free(&env); }

View File

@ -28,18 +28,12 @@ typedef struct {
void *context_data; void *context_data;
} Route; } 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 #if MY_DEBUG
ROUTE_HANDLER(hotreload_js); void route_build_id(struct mg_http_message *msg, Route_Result *result, void *context_data);
ROUTE_HANDLER(build_id);
#endif #endif
ROUTE_HANDLER(home); void route_page_not_found(struct mg_http_message *msg, Route_Result *result, void *context_data);
ROUTE_HANDLER(generic_blog); void route_home(struct mg_http_message *msg, Route_Result *result, void *context_data);
ROUTE_HANDLER(blog); 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_ #endif // ROUTES_H_

11
timer.c
View File

@ -3,22 +3,27 @@
#include <stdio.h> #include <stdio.h>
#include "timer.h" #include "timer.h"
#include "locked.h"
time_t rawtime; locked(time_t) rawtime;
void start_timer(void) void start_timer(void)
{ {
time(&rawtime); lockx(&rawtime);
time(&rawtime.value);
unlockx(&rawtime);
} }
void get_timer_string(char *output, size_t size) void get_timer_string(char *output, size_t size)
{ {
lockx(&rawtime);
struct tm * timeinfo; struct tm * timeinfo;
timeinfo = localtime(&rawtime); timeinfo = localtime(&rawtime.value);
snprintf(output, size, "[%02d %02d %d %02d:%02d:%02d]", timeinfo->tm_mday, snprintf(output, size, "[%02d %02d %d %02d:%02d:%02d]", timeinfo->tm_mday,
timeinfo->tm_mon + 1, timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_year + 1900,
timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
unlockx(&rawtime);
} }