https://gitlab.synchro.net/main/sbbs/-/issues/1099#note_8576
Tried to create a small C++ reproduction case for this issue, unsuccessfully.
Created xpdev/strlisttest.cpp:
```
#include "str_list.h"
#include "threadwrap.h"
#include "genwrap.h"
#include "dirwrap.h"
#include <atomic>
#include <mutex>
#include <time.h>
static char* process_findstr_item(size_t index, char *str, void* cbdata)
{
SKIP_WHITESPACE(str);
truncnl(str);
return c_unescape_str(str);
}
str_list_t findstr_list(const char* fname)
{
FILE* fp;
str_list_t list;
if ((fp = fopen(fname, "r")) == NULL)
return NULL;
list = strListReadFile(fp, NULL, 1000);
strListModifyEach(list, process_findstr_item, /* cbdata: */ NULL);
printf("Read %s\n", fname);
fclose(fp);
return list;
}
class filterFile {
public:
filterFile() {
pthread_mutex_init(&mutex, nullptr);
}
filterFile(const char* fname) : filterFile() {
init(fname);
}
void init(const char* fname) {
strlcpy(this->fname, fname, sizeof this->fname);
}
filterFile(const filterFile&) = delete;
filterFile& operator=(const filterFile&) = delete;
~filterFile() {
strListFree(&list);
pthread_mutex_destroy(&mutex);
}
void reset() {
fread_count = 0;
total_found = 0;
timestamp = 0;
lastftime_check = 0;
strListFree(&list);
}
std::atomic<uint> fread_count{};
std::atomic<uint> total_found{};
time_t fchk_interval{1}; // seconds
char fname[MAX_PATH + 1]{};
bool listed(const char* str1, const char* str2 = nullptr, struct trash* details = nullptr) {
bool result;
time_t now = time(nullptr);
if (fchk_interval) {
pthread_mutex_lock(&mutex);
if ((now - lastftime_check) >= fchk_interval) {
lastftime_check = now;
time_t latest = fdate(fname);
if (latest > timestamp) {
strListFree(&list);
list = findstr_list(fname);
timestamp = latest;
++fread_count;
}
}
result = false; //trash_in_list(str1, str2, list, details);
pthread_mutex_unlock(&mutex);
}
if (result)
++total_found;
return result;
}
private:
str_list_t list{};
pthread_mutex_t mutex{};
time_t lastftime_check{};
time_t timestamp{};
};
filterFile filter;
void thread(void* arg) {
filter.listed("");
}
int main(int argc, char ** argv) {
for (int i = 1; i < argc; ++i) {
filter.init(argv[i]);
_beginthread(thread, 0, nullptr);
SLEEP(2000);
printf("Freeing list\n");
filter.reset();
printf("Done freeing list\n");
}
return 0;
}
```
Build it with this command-line replicating all the options to be sbbs.dll Win32-debug and adding address-sanitizer:
```
cl /GS /analyze- /W3 /Zc:wchar_t /Zi /Gm- /Od /Zc:inline /fp:precise /D "_DEBUG" /D "WIN32" /D "_LIB" /D "LINK_LIST_THREADSAFE" /D "WINVER=0x600" /D "_WIN32_WINNT=0x600" /D "HAS_INTTYPES_H" /D "HAS_STDINT_H" /D "XPDEV_THREAD_SAFE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "_VC80_UPGRADE=0x0600" /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /RTC1 /std:c17 /arch:IA32 /Gd /Oy- /MTd /FC /EHsc /nologo /diagnostics:column /fsanitize=address -DHAS_STDINT_H strlisttest.cpp str_list.c genwrap.c xpprintf.c dirwrap.c threadwrap.c
```
The resulting executable runs just fine:
```
C:\sbbs\src\xpdev>strlisttest s:\sbbs\text\ip.can s:\sbbs\text\host.can s:\sbbs\text\ip.can s:\sbbs\text\host.can s:\sbbs\text\ip-silent.can
Read s:\sbbs\text\ip.can
Freeing list
Done freeing list
Read s:\sbbs\text\host.can
Freeing list
Done freeing list
Read s:\sbbs\text\ip.can
Freeing list
Done freeing list
Read s:\sbbs\text\host.can
Freeing list
Done freeing list
Read s:\sbbs\text\ip-silent.can
Freeing list
Done freeing list
```
I'm out of ideas for now.
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)