From 30b3cff6574fbeeda4cfcc54c92e955b04180489 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Apr 2016 12:23:51 +0200 Subject: [PATCH 1/6] fix a crash in write_game caused by remove_empty_factions https://bugs.eressea.de/view.php?id=2201 --- src/buildno.h | 2 +- src/kernel/faction.c | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/buildno.h b/src/buildno.h index 3a7947aaa..1b97adf8b 100644 --- a/src/buildno.h +++ b/src/buildno.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 8 -#define VERSION_BUILD 7 +#define VERSION_BUILD 8 diff --git a/src/kernel/faction.c b/src/kernel/faction.c index edb8a9e2f..2699e1b09 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -74,9 +74,6 @@ faction *factions; static void free_faction(faction * f) { funhash(f); - if (f->alliance && f->alliance->_leader == f) { - setalliance(f, 0); - } if (f->msgs) { free_messagelist(f->msgs->begin); free(f->msgs); @@ -454,7 +451,7 @@ void destroyfaction(faction ** fp) } #endif - if (f->alliance && f->alliance->_leader == f) { + if (f->alliance) { setalliance(f, 0); } @@ -681,8 +678,6 @@ void remove_empty_factions(void) if (!(f->_alive && f->units!=NULL) && !fval(f, FFL_NOIDLEOUT)) { log_debug("dead: %s", factionname(f)); destroyfaction(fp); - free_faction(f); - free(f); } else { fp = &(*fp)->next; From b2e8c75c0261d9082e1c9ceadb5368f099fa5fd8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Apr 2016 12:37:26 +0200 Subject: [PATCH 2/6] add a test that should have crashed before my fix. --- src/kernel/faction.test.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index 19b4da883..10bc0683b 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -13,6 +13,7 @@ #include "monster.h" #include #include +#include #include #include @@ -46,8 +47,10 @@ static void test_remove_empty_factions_alliance(CuTest *tc) { al = makealliance(0, "Hodor"); setalliance(f, al); CuAssertPtrEquals(tc, f, alliance_get_leader(al)); + CuAssertIntEquals(tc, 1, ql_length(al->members)); remove_empty_factions(); CuAssertPtrEquals(tc, 0, al->_leader); + CuAssertIntEquals(tc, 0, ql_length(al->members)); test_cleanup(); } @@ -61,6 +64,9 @@ static void test_remove_empty_factions(CuTest *tc) { f = test_create_faction(0); fno = f->no; remove_empty_factions(); + CuAssertIntEquals(tc, false, f->_alive); + CuAssertPtrEquals(tc, fm, factions); + CuAssertPtrEquals(tc, NULL, fm->next); CuAssertPtrEquals(tc, 0, findfaction(fno)); CuAssertPtrEquals(tc, fm, get_monsters()); test_cleanup(); From 1fa16931195f38c71a5030136bee0ae74ee5afc5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 1 May 2016 13:36:00 +0200 Subject: [PATCH 3/6] test multiple loggers --- src/test_eressea.c | 1 + src/util/CMakeLists.txt | 1 + src/util/log.test.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 src/util/log.test.c diff --git a/src/test_eressea.c b/src/test_eressea.c index a9b9b941c..a628d9009 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -84,6 +84,7 @@ int RunAllTests(int argc, char *argv[]) ADD_SUITE(umlaut); ADD_SUITE(unicode); ADD_SUITE(strings); + ADD_SUITE(log); ADD_SUITE(rng); /* items */ ADD_SUITE(xerewards); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index a441bcfe7..a34d6cbb0 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -8,6 +8,7 @@ attrib.test.c strings.test.c bsdstring.test.c functions.test.c +log.test.c umlaut.test.c unicode.test.c rng.test.c diff --git a/src/util/log.test.c b/src/util/log.test.c new file mode 100644 index 000000000..017481e48 --- /dev/null +++ b/src/util/log.test.c @@ -0,0 +1,33 @@ +#include + +#include "log.h" + +#include +#include + +void log_string(void *data, int level, const char *module, const char *format, va_list args) { + char *str = (char *)data; + const char *arg = va_arg(args, const char *); + strncpy(str, arg, 32); +} + +static void test_logging(CuTest * tc) +{ + char str1[32]; + char str2[32]; + int id1 = log_create(LOG_CPWARNING, str1, log_string); + int id2 = log_create(LOG_CPWARNING, str2, log_string); + CuAssertTrue(tc, id1!=id2); + log_warning("Hello %s", "World"); + CuAssertStrEquals(tc, str1, "World"); + CuAssertStrEquals(tc, str2, "World"); + log_destroy(id1); + log_destroy(id2); +} + +CuSuite *get_log_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_logging); + return suite; +} From 41277ed5ee97b992122e8e42508669c2f50ba569 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 1 May 2016 13:39:25 +0200 Subject: [PATCH 4/6] prove that logging is broken (new test segfaults) --- src/util/log.c | 20 ++++++++++++++++++-- src/util/log.h | 3 ++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/util/log.c b/src/util/log.c index 958e26e2f..b5a8ef9fd 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -35,18 +35,34 @@ typedef struct logger { void(*log)(void *data, int level, const char *module, const char *format, va_list args); void *data; int flags; + int id; struct logger *next; } logger; static logger *loggers; +static int log_id; -void log_create(int flags, void *data, log_fun call) { +int log_create(int flags, void *data, log_fun call) { logger *lgr = malloc(sizeof(logger)); lgr->log = call; lgr->flags = flags; lgr->data = data; lgr->next = loggers; loggers = lgr; + return lgr->id = ++log_id; +} + +void log_destroy(int id) { + logger ** lp = &loggers; + while (*lp) { + logger *lg = *lp; + if (lg->id==id) { + *lp = lg->next; + free(lg); + break; + } + lp = &lg->next; + } } #define MAXLENGTH 4096 /* because I am lazy, CP437 output is limited to this many chars */ @@ -138,7 +154,6 @@ static void _log_write(FILE * stream, int codepage, const char *format, va_list if (codepage) { char buffer[MAXLENGTH]; char converted[MAXLENGTH]; - vsnprintf(buffer, sizeof(buffer), format, args); if (cp_convert(buffer, converted, MAXLENGTH, codepage) == 0) { fputs(converted, stream); @@ -177,6 +192,7 @@ static void log_write(int flags, const char *module, const char *format, va_list int level = flags & LOG_LEVELS; if (lg->flags & level) { int dupe = 0; + if (lg->flags & LOG_BRIEF) { dupe = check_dupe(format, level); } diff --git a/src/util/log.h b/src/util/log.h index 8fd8f2a95..d19c4cf9b 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -38,7 +38,8 @@ extern "C" { typedef void(*log_fun)(void *data, int level, const char *module, const char *format, va_list args); - void log_create(int flags, void *data, log_fun call); + int log_create(int flags, void *data, log_fun call); + void log_destroy(int id); void log_to_file(int flags, FILE *out); extern int log_flags; From f24b1c1cdcdea66f83d87150f2819538d7179a72 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 1 May 2016 13:40:01 +0200 Subject: [PATCH 5/6] fix multi-logging --- src/util/log.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/util/log.c b/src/util/log.c index b5a8ef9fd..cc9fafb92 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -192,13 +192,16 @@ static void log_write(int flags, const char *module, const char *format, va_list int level = flags & LOG_LEVELS; if (lg->flags & level) { int dupe = 0; + va_list copy; + va_copy(copy, args); if (lg->flags & LOG_BRIEF) { dupe = check_dupe(format, level); } if (dupe == 0) { - lg->log(lg->data, level, NULL, format, args); + lg->log(lg->data, level, NULL, format, copy); } + va_end(copy); } } } From 0557aa84acb5c5e5250b68a4a1839d88a4ac76aa Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 1 May 2016 13:40:10 +0200 Subject: [PATCH 6/6] release version 3.8.9 --- src/buildno.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/buildno.h b/src/buildno.h index 1b97adf8b..7f9758de0 100644 --- a/src/buildno.h +++ b/src/buildno.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 8 -#define VERSION_BUILD 8 +#define VERSION_BUILD 9