commit 14169f5bc456ec45a746ecd554adfa825a6e9f5a
parent 1796e089187e177cda34159ec131000799698aee
Author: Louis Burda <quent.burda@gmail.com>
Date: Thu, 8 Jul 2021 11:29:46 +0200
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
Diffstat:
7 files changed, 106 insertions(+), 63 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -62,6 +62,13 @@ stack_ind(struct stack *stack, int search)
}
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)
{
return c && strchr(wsset, 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
@@ -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
@@ -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
@@ -144,4 +144,3 @@ strpfcmp(const char *prefix, const char *str)
{
return strncmp(prefix, str, strlen(prefix));
}
-