能否在不同线程调用pthread_key_create与pthread_key_delete?LMDB需明确规则吗?
问题背景详情
我们在使用lmdb数据库库时,在极罕见且难以复现的场景下遇到SIGSEGV错误。通过核心转储得到的堆栈跟踪如下:
#0 in mdb_env_reader_dest (ptr=...) at .../mdb.c: 4935 #1 in __nptl_deallocate_tsd () at pthread_create.c:301 ...
堆栈跟踪指向的代码行(因我们尝试修改修复,行号有所不同)。
经过一段时间排查,唯一合理的解释是:当从非主线程关闭lmdb环境时,lmdb源码中某两行代码之间存在竞态条件。后者会删除键并调用自定义析构函数mdb_env_reader_dest,而根据lmdb文档,在释放资源后尝试使用会导致SIGSEGV。
核心问题
我个人认为pthread_key_create和pthread_key_delete的文档描述存在歧义,不清楚其指代的是函数调用本身还是指针指向的数据。文档原文如下:
The associated destructor functions used to free thread-specific data at thread exit time are only guaranteed to work correctly when called in the thread that allocated the thread-specific data.
因此核心问题是:若在不同线程分别调用mdb_env_open和mdb_env_close(进而在不同线程调用pthread_key_create和pthread_key_delete),能否保证行为正确?
我未在lmdb文档中找到相关要求,最接近的内容仅提及资源释放后使用会导致错误,但并未提及mdb_env_open函数。
内容的提问来源于stack exchange,提问作者The Quantum Physicist

