From 14169f5bc456ec45a746ecd554adfa825a6e9f5a Mon Sep 17 00:00:00 2001 From: Louis Burda Date: Thu, 8 Jul 2021 11:29:46 +0200 Subject: added script to host service locally on port for easier memory leak debugging and checking in/out/stderr, also made file locking / unlocking less racey now flush locks after acquiring and before unlocking --- do.sh | 3 +++ run-proxy.sh | 3 +++ service/src/main.c | 66 +++++++++++++++++++++++++++++++-------------------- service/src/stlfile.c | 29 +++++++++++++++------- service/src/util.c | 1 - src/main.c | 66 +++++++++++++++++++++++++++++++-------------------- src/util.c | 1 - 7 files changed, 106 insertions(+), 63 deletions(-) create mode 100755 run-proxy.sh diff --git a/do.sh b/do.sh index 5e0432c..e58f187 100644 --- a/do.sh +++ b/do.sh @@ -84,6 +84,9 @@ elif [ "$1" == "ci-test" ]; then docker-compose -f service/docker-compose.yml down docker-compose -f checker/docker-compose.yml down +elif [ "$1" == "host-local" ]; then + RESULTDIR=service/data/uploads socat -T180 -s TCP-LISTEN:9090,nodelay,reuseaddr,fork \ + EXEC:./run-proxy.sh,raw,pty,echo=0,stderr elif [ "$1" == "parse-log" ]; then python3 -c ' #!/usr/bin/env python3 diff --git a/run-proxy.sh b/run-proxy.sh new file mode 100755 index 0000000..efc1450 --- /dev/null +++ b/run-proxy.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +tee /tmp/run-log-in-$$ | valgrind --show-leak-kinds=all --leak-check=full service/src/build/stldoctor 2>/tmp/run-log-err-$$ | tee /tmp/run-log-out-$$ diff --git a/service/src/main.c b/service/src/main.c index 6b7fb03..4b2786d 100644 --- a/service/src/main.c +++ b/service/src/main.c @@ -48,6 +48,35 @@ struct parseinfo cached = { 0 }; char *resultdir; int echo = 0, loggedin = 0; +FILE* +lockfile(const char *path, const char* mode, int locktype) +{ + FILE *f; + + if (!(f = fopen(path, mode))) { + ERR("Failed to open index file\n"); + return NULL; + } + if (flock(fileno(f), locktype)) { + fclose(f); + ERR("Failed to acquire lock on index file\n"); + return NULL; + } + fflush(f); + return f; +} + +void +unlockfile(FILE **f) +{ + if (*f) { + fflush(*f); + flock(fileno(*f), LOCK_UN); + fclose(*f); + *f = NULL; + } +} + int save_submission(struct parseinfo *info, char *stldata, int stlsize) { @@ -72,12 +101,11 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) FCLOSE(f); indexpath = aprintf("%s/.index", resultdir); - if (!(f = fopen(indexpath, "a+"))) goto fail; - flock(fileno(f), LOCK_EX); + if (!(f = lockfile(indexpath, "a+", LOCK_EX))) + goto exit; fwrite(modeldir, 1, strlen(modeldir), f); fputc('\n', f); - flock(fileno(f), LOCK_UN); - FCLOSE(f); + unlockfile(&f); exit: FCLOSE(f); @@ -278,11 +306,8 @@ search_cmd(const char *arg) } indexpath = aprintf("%s/.index", resultdir); - if (!(f = fopen(indexpath, "r"))) { - ERR("Sorry, no files currently available\n"); + if (!(f = lockfile(indexpath, "r", LOCK_SH))) goto exit; - } - flock(fileno(f), LOCK_SH); reslen = matchlen = 0; filename = aprintf("%s%s", loggedin ? "." : "", hash); @@ -307,8 +332,7 @@ search_cmd(const char *arg) } } - flock(fileno(f), LOCK_UN); - fclose(f); + unlockfile(&f); if (!reslen) { ERR("Sorry, no files matching that name\n"); @@ -333,7 +357,6 @@ exit: free(filename); free(seldir); free(indexpath); - return; } void @@ -349,14 +372,10 @@ list_cmd(const char *arg) } path = aprintf("%s/.index", resultdir); - if (!(f = fopen(path, "r"))) { - ERR("Failed to get files index\n"); - free(path); - return; - } + f = lockfile(path, "r", LOCK_SH); free(path); + if (!f) return; - flock(fileno(f), LOCK_SH); while (fgets(buf, sizeof(buf), f)) { if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; @@ -372,8 +391,8 @@ list_cmd(const char *arg) if (fn) fclose(fn); free(path); } - flock(fileno(f), LOCK_UN); - fclose(f); + + unlockfile(&f); } void @@ -405,17 +424,12 @@ auth_cmd(const char *arg) if (!existed) { indexpath = aprintf("%s/.index", resultdir); - if (!(f = fopen(indexpath, "a+"))) { - free(indexpath); - ERR("Auth failed!\n"); + if (!(f = lockfile(indexpath, "a+", LOCK_EX))) return; - } - flock(fileno(f), LOCK_EX); fputc('.', f); fwrite(hash, 1, strlen(hash), f); fputc('\n', f); - flock(fileno(f), LOCK_UN); - fclose(f); + unlockfile(&f); free(indexpath); } diff --git a/service/src/stlfile.c b/service/src/stlfile.c index 7c067f3..04e6727 100644 --- a/service/src/stlfile.c +++ b/service/src/stlfile.c @@ -61,6 +61,13 @@ stack_ind(struct stack *stack, int search) return -1; } +int +stack_top_eq(struct stack *stack, int cmp) +{ + if (!stack->count) return 0; + return stack->data[stack->count-1] == cmp; +} + int isws(char c) { @@ -131,11 +138,11 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) while ((kw = consume_keyword(&bp))) { switch (kw) { case KW_SOLID_BEGIN: - stack_push(&states, STATE_SOLID); - if (stack_ind(&states, KW_SOLID_BEGIN) != -1) { - FMT_ERR("Multiple nested solids!\n"); + if (states.count) { + FMT_ERR("Improper nesting, solid not top-level in STL\n"); goto fail; } + stack_push(&states, STATE_SOLID); tmp = bp; if (!consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { @@ -162,11 +169,11 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) } break; case KW_LOOP_BEGIN: - stack_push(&states, STATE_LOOP); - if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { - FMT_ERR("Multiple nested loops!\n"); + if (!stack_top_eq(&states, STATE_FACET)) { + FMT_ERR("Loop parent is not a facet!\n"); goto fail; } + stack_push(&states, STATE_LOOP); break; case KW_LOOP_END: if ((kw = stack_pop(&states)) != STATE_LOOP) { @@ -177,11 +184,11 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) info->loopcount++; break; case KW_FACET_BEGIN: - stack_push(&states, STATE_FACET); - if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { - FMT_ERR("Multiple nested facets!\n"); + if (!stack_top_eq(&states, STATE_SOLID)) { + FMT_ERR("Facet parent is not a solid!\n"); goto fail; } + stack_push(&states, STATE_FACET); for (i = 0; i < 3; i++) { if (!(arg = consume_arg(&bp, &end))) { FMT_ERR("Facet with < 3 args!\n"); @@ -202,6 +209,10 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) } break; case KW_VERTEX: + if (!stack_top_eq(&states, STATE_LOOP)) { + FMT_ERR("Vertex parent is not a loop!\n"); + goto fail; + } for (i = 0; i < 3; i++) { if (!(arg = consume_arg(&bp, &end))) { FMT_ERR("Vertex with < 3 args\n"); diff --git a/service/src/util.c b/service/src/util.c index ba4f13f..c8274d8 100644 --- a/service/src/util.c +++ b/service/src/util.c @@ -138,4 +138,3 @@ strpfcmp(const char *prefix, const char *str) { return strncmp(prefix, str, strlen(prefix)); } - diff --git a/src/main.c b/src/main.c index 12d59c4..b639f6a 100644 --- a/src/main.c +++ b/src/main.c @@ -48,6 +48,35 @@ struct parseinfo cached = { 0 }; char *resultdir; int echo = 0, loggedin = 0; +FILE* +lockfile(const char *path, const char* mode, int locktype) +{ + FILE *f; + + if (!(f = fopen(path, mode))) { + ERR("Failed to open index file\n"); + return NULL; + } + if (flock(fileno(f), locktype)) { + fclose(f); + ERR("Failed to acquire lock on index file\n"); + return NULL; + } + fflush(f); /* discard buffered data */ + return f; +} + +void +unlockfile(FILE **f) +{ + if (*f) { + fflush(*f); /* flush output to file */ + flock(fileno(*f), LOCK_UN); + fclose(*f); + *f = NULL; + } +} + int save_submission(struct parseinfo *info, char *stldata, int stlsize) { @@ -72,12 +101,11 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) FCLOSE(f); indexpath = aprintf("%s/.index", resultdir); - if (!(f = fopen(indexpath, "a+"))) goto fail; - flock(fileno(f), LOCK_EX); + if (!(f = lockfile(indexpath, "a+", LOCK_EX))) + goto exit; fwrite(modeldir, 1, strlen(modeldir), f); fputc('\n', f); - flock(fileno(f), LOCK_UN); - FCLOSE(f); + unlockfile(&f); exit: FCLOSE(f); @@ -280,11 +308,8 @@ search_cmd(const char *arg) /* open and lock index file access */ indexpath = aprintf("%s/.index", resultdir); - if (!(f = fopen(indexpath, "r"))) { - ERR("Sorry, no files currently available\n"); + if (!(f = lockfile(indexpath, "r", LOCK_SH))) goto exit; - } - flock(fileno(f), LOCK_SH); /* output lines that have hash as prefix */ reslen = matchlen = 0; @@ -310,8 +335,7 @@ search_cmd(const char *arg) } } - flock(fileno(f), LOCK_UN); - fclose(f); + unlockfile(&f); if (!reslen) { ERR("Sorry, no files matching that name\n"); @@ -337,7 +361,6 @@ exit: free(filename); free(seldir); free(indexpath); - return; } void @@ -353,14 +376,10 @@ list_cmd(const char *arg) } path = aprintf("%s/.index", resultdir); - if (!(f = fopen(path, "r"))) { - ERR("Failed to get files index\n"); - free(path); - return; - } + f = lockfile(path, "r", LOCK_SH); free(path); + if (!f) return; - flock(fileno(f), LOCK_SH); while (fgets(buf, sizeof(buf), f)) { if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; @@ -376,8 +395,8 @@ list_cmd(const char *arg) if (fn) fclose(fn); free(path); } - flock(fileno(f), LOCK_UN); - fclose(f); + + unlockfile(&f); } void @@ -409,17 +428,12 @@ auth_cmd(const char *arg) if (!existed) { indexpath = aprintf("%s/.index", resultdir); - if (!(f = fopen(indexpath, "a+"))) { - free(indexpath); - ERR("Auth failed!\n"); + if (!(f = lockfile(indexpath, "a+", LOCK_EX))) return; - } - flock(fileno(f), LOCK_EX); fputc('.', f); fwrite(hash, 1, strlen(hash), f); fputc('\n', f); - flock(fileno(f), LOCK_UN); - fclose(f); + unlockfile(&f); free(indexpath); } diff --git a/src/util.c b/src/util.c index 241c2f4..2832f03 100644 --- a/src/util.c +++ b/src/util.c @@ -144,4 +144,3 @@ strpfcmp(const char *prefix, const char *str) { return strncmp(prefix, str, strlen(prefix)); } - -- cgit v1.2.3-71-gd317