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)