Add lock for loading so.
This commit is contained in:
@ -2301,6 +2301,10 @@ void delete_file_handle(const char* library_path)
|
|||||||
DynamicFileList* file_scanner = NULL;
|
DynamicFileList* file_scanner = NULL;
|
||||||
DynamicFileList* pre_file_scanner = file_list;
|
DynamicFileList* pre_file_scanner = file_list;
|
||||||
|
|
||||||
|
AutoMutexLock libraryLock(&file_list_lock);
|
||||||
|
libraryLock.lock();
|
||||||
|
|
||||||
|
|
||||||
char* fullname = expand_dynamic_library_name(library_path);
|
char* fullname = expand_dynamic_library_name(library_path);
|
||||||
for (file_scanner = file_list; file_scanner != NULL; file_scanner = file_scanner->next) {
|
for (file_scanner = file_list; file_scanner != NULL; file_scanner = file_scanner->next) {
|
||||||
if (strncmp(fullname, file_scanner->filename, strlen(fullname) + 1) == 0) {
|
if (strncmp(fullname, file_scanner->filename, strlen(fullname) + 1) == 0) {
|
||||||
@ -2323,6 +2327,8 @@ void delete_file_handle(const char* library_path)
|
|||||||
pre_file_scanner = file_scanner;
|
pre_file_scanner = file_scanner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libraryLock.unLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1064,6 +1064,7 @@ LocalSysDBCache::LocalSysDBCache()
|
|||||||
|
|
||||||
void AtEOXact_SysDBCache(bool is_commit)
|
void AtEOXact_SysDBCache(bool is_commit)
|
||||||
{
|
{
|
||||||
|
ResourceOwnerReleasePthreadMutex(t_thrd.lsc_cxt.local_sysdb_resowner, is_commit);
|
||||||
if (!EnableLocalSysCache()) {
|
if (!EnableLocalSysCache()) {
|
||||||
ResourceOwnerReleaseRelationRef(t_thrd.lsc_cxt.local_sysdb_resowner, is_commit);
|
ResourceOwnerReleaseRelationRef(t_thrd.lsc_cxt.local_sysdb_resowner, is_commit);
|
||||||
return;
|
return;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "utils/hsearch.h"
|
#include "utils/hsearch.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "utils/syscall_lock.h"
|
#include "utils/syscall_lock.h"
|
||||||
|
#include "postmaster/postmaster.h"
|
||||||
#include "storage/file/fio_device.h"
|
#include "storage/file/fio_device.h"
|
||||||
|
|
||||||
/* Max size of error message of dlopen */
|
/* Max size of error message of dlopen */
|
||||||
@ -167,6 +168,36 @@ PGFunction lookup_external_function(void* filehandle, const char* funcname)
|
|||||||
return (PGFunction)pg_dlsym(filehandle, funcname);
|
return (PGFunction)pg_dlsym(filehandle, funcname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* release all library at proc exit.
|
||||||
|
*/
|
||||||
|
void internal_delete_library()
|
||||||
|
{
|
||||||
|
DynamicFileList* file_scanner = NULL;
|
||||||
|
|
||||||
|
AutoMutexLock libraryLock(&file_list_lock);
|
||||||
|
libraryLock.lock();
|
||||||
|
|
||||||
|
while (file_list != NULL) {
|
||||||
|
file_scanner = file_list;
|
||||||
|
file_list = file_list->next;
|
||||||
|
#ifndef ENABLE_MEMORY_CHECK
|
||||||
|
/*
|
||||||
|
* in the senario of ImmediateShutdown, it is not safe to close plugin
|
||||||
|
* as PM thread will not wait for all children threads exist(will send SIGQUIT signal) referring to pmdie
|
||||||
|
*/
|
||||||
|
if (g_instance.status != ImmediateShutdown && file_scanner->handle != NULL) {
|
||||||
|
(void)pg_dlclose(file_scanner->handle);
|
||||||
|
file_scanner->handle = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pfree((char*)file_scanner);
|
||||||
|
file_scanner = NULL;
|
||||||
|
}
|
||||||
|
file_list = file_tail = NULL;
|
||||||
|
libraryLock.unLock();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load the specified dynamic-link library file, unless it already is
|
* Load the specified dynamic-link library file, unless it already is
|
||||||
* loaded. Return the pg_dl* handle for the file.
|
* loaded. Return the pg_dl* handle for the file.
|
||||||
@ -186,6 +217,9 @@ void* internal_load_library(const char* libname)
|
|||||||
char* file = last_dir_separator(libname);
|
char* file = last_dir_separator(libname);
|
||||||
file = (file == NULL) ? ((char*)libname) : (file + 1);
|
file = (file == NULL) ? ((char*)libname) : (file + 1);
|
||||||
|
|
||||||
|
AutoMutexLock libraryLock(&file_list_lock);
|
||||||
|
libraryLock.lock();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the list of loaded FILES to see if the file has been loaded.
|
* Scan the list of loaded FILES to see if the file has been loaded.
|
||||||
*/
|
*/
|
||||||
@ -367,6 +401,8 @@ void* internal_load_library(const char* libname)
|
|||||||
u_sess->fmgr_cxt.file_init_tail = file_init_scanner;
|
u_sess->fmgr_cxt.file_init_tail = file_init_scanner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libraryLock.unLock();
|
||||||
|
|
||||||
return file_scanner->handle;
|
return file_scanner->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,8 +526,9 @@ static void internal_unload_library(const char* libname)
|
|||||||
* inode, else internal_load_library() will still think it's present.
|
* inode, else internal_load_library() will still think it's present.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AutoMutexLock libraryLock(&dlerror_lock);
|
AutoMutexLock dlerrorLock(&dlerror_lock);
|
||||||
|
dlerrorLock.lock();
|
||||||
|
AutoMutexLock libraryLock(&file_list_lock);
|
||||||
libraryLock.lock();
|
libraryLock.lock();
|
||||||
|
|
||||||
for (file_scanner = file_list; file_scanner != NULL; file_scanner = nxt) {
|
for (file_scanner = file_list; file_scanner != NULL; file_scanner = nxt) {
|
||||||
@ -523,6 +560,7 @@ static void internal_unload_library(const char* libname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
libraryLock.unLock();
|
libraryLock.unLock();
|
||||||
|
dlerrorLock.unLock();
|
||||||
|
|
||||||
#endif /* NOT_USED */
|
#endif /* NOT_USED */
|
||||||
}
|
}
|
||||||
|
@ -1799,7 +1799,7 @@ void PrintResourceOwnerLeakWarning()
|
|||||||
ereport(WARNING, (errmsg("resource owner \"%s\" may leak", IsolatedResourceOwner->name)));
|
ereport(WARNING, (errmsg("resource owner \"%s\" may leak", IsolatedResourceOwner->name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceOwnerReleasePthreadMutex()
|
void ResourceOwnerReleaseAllXactPthreadMutex()
|
||||||
{
|
{
|
||||||
ResourceOwner owner = t_thrd.utils_cxt.TopTransactionResourceOwner;
|
ResourceOwner owner = t_thrd.utils_cxt.TopTransactionResourceOwner;
|
||||||
ResourceOwner child;
|
ResourceOwner child;
|
||||||
@ -2012,6 +2012,23 @@ void ResourceOwnerForgetPthreadRWlock(ResourceOwner owner, pthread_rwlock_t* pRW
|
|||||||
errmsg("pthread rwlock is not owned by resource owner %s", owner->name)));
|
errmsg("pthread rwlock is not owned by resource owner %s", owner->name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace)
|
||||||
|
{
|
||||||
|
pthread_mutex_t** mutexs = owner->pThdMutexs;
|
||||||
|
int ns1 = owner->nPthreadMutex - 1;
|
||||||
|
|
||||||
|
if (!owner->valid) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = ns1; i >= 0; i--) {
|
||||||
|
if (mutexs[i] == pMutex) {
|
||||||
|
return PthreadMutexUnlock(owner, pMutex, trace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ResourceOwnerEnlargeLocalCatCList(ResourceOwner owner)
|
void ResourceOwnerEnlargeLocalCatCList(ResourceOwner owner)
|
||||||
{
|
{
|
||||||
int newmax;
|
int newmax;
|
||||||
@ -2224,6 +2241,17 @@ void ResourceOwnerForgetGlobalBaseEntry(ResourceOwner owner, GlobalBaseEntry* en
|
|||||||
errmsg("the global base entry is not owned by resource owner %s", owner->name)));
|
errmsg("the global base entry is not owned by resource owner %s", owner->name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResourceOwnerReleasePthreadMutex(ResourceOwner owner, bool isCommit)
|
||||||
|
{
|
||||||
|
while (owner->nPthreadMutex > 0) {
|
||||||
|
if (isCommit) {
|
||||||
|
PrintGlobalSysCacheLeakWarning(owner, "MutexLock");
|
||||||
|
}
|
||||||
|
/* unlock do -- */
|
||||||
|
PthreadMutexUnlock(owner, owner->pThdMutexs[owner->nPthreadMutex - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ResourceOwnerReleaseRWLock(ResourceOwner owner, bool isCommit)
|
void ResourceOwnerReleaseRWLock(ResourceOwner owner, bool isCommit)
|
||||||
{
|
{
|
||||||
while (owner->nPthreadRWlock > 0) {
|
while (owner->nPthreadRWlock > 0) {
|
||||||
|
@ -32,6 +32,8 @@ syscalllock env_lock;
|
|||||||
syscalllock dlerror_lock;
|
syscalllock dlerror_lock;
|
||||||
syscalllock kerberos_conn_lock;
|
syscalllock kerberos_conn_lock;
|
||||||
syscalllock read_cipher_lock;
|
syscalllock read_cipher_lock;
|
||||||
|
syscalllock file_list_lock;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @Description: Atomic set val into *ptr in a 32-bit address, and return the previous pointed by ptr
|
* @Description: Atomic set val into *ptr in a 32-bit address, and return the previous pointed by ptr
|
||||||
|
@ -544,4 +544,5 @@ static void syscall_lock_init(void)
|
|||||||
syscalllockInit(&dlerror_lock);
|
syscalllockInit(&dlerror_lock);
|
||||||
syscalllockInit(&kerberos_conn_lock);
|
syscalllockInit(&kerberos_conn_lock);
|
||||||
syscalllockInit(&read_cipher_lock);
|
syscalllockInit(&read_cipher_lock);
|
||||||
|
syscalllockInit(&file_list_lock);
|
||||||
}
|
}
|
||||||
|
@ -904,7 +904,7 @@ void StreamNodeGroup::destroy(StreamObjStatus status)
|
|||||||
|
|
||||||
/* We must relase all pthread mutex by my thread, Or it will dead lock. But it is not a good solution. */
|
/* We must relase all pthread mutex by my thread, Or it will dead lock. But it is not a good solution. */
|
||||||
// lock the same thread mutex can't be conflict in one thread.
|
// lock the same thread mutex can't be conflict in one thread.
|
||||||
ResourceOwnerReleasePthreadMutex();
|
ResourceOwnerReleaseAllXactPthreadMutex();
|
||||||
|
|
||||||
WaitState oldStatus = pgstat_report_waitstatus(STATE_STREAM_WAIT_NODEGROUP_DESTROY);
|
WaitState oldStatus = pgstat_report_waitstatus(STATE_STREAM_WAIT_NODEGROUP_DESTROY);
|
||||||
|
|
||||||
@ -954,7 +954,7 @@ void StreamNodeGroup::syncQuit(StreamObjStatus status)
|
|||||||
|
|
||||||
/* We must relase all pthread mutex by my thread, Or it will dead lock. But it is not a good solution. */
|
/* We must relase all pthread mutex by my thread, Or it will dead lock. But it is not a good solution. */
|
||||||
// lock the same thread mutex can't be conflict in one thread.
|
// lock the same thread mutex can't be conflict in one thread.
|
||||||
ResourceOwnerReleasePthreadMutex();
|
ResourceOwnerReleaseAllXactPthreadMutex();
|
||||||
|
|
||||||
WaitState oldStatus = pgstat_report_waitstatus(STATE_STREAM_WAIT_THREAD_SYNC_QUIT);
|
WaitState oldStatus = pgstat_report_waitstatus(STATE_STREAM_WAIT_THREAD_SYNC_QUIT);
|
||||||
|
|
||||||
|
@ -157,8 +157,6 @@ void proc_exit_prepare(int code);
|
|||||||
*/
|
*/
|
||||||
void proc_exit(int code)
|
void proc_exit(int code)
|
||||||
{
|
{
|
||||||
DynamicFileList* file_scanner = NULL;
|
|
||||||
|
|
||||||
if (ENABLE_DMS && t_thrd.proc_cxt.MyProcPid == PostmasterPid) {
|
if (ENABLE_DMS && t_thrd.proc_cxt.MyProcPid == PostmasterPid) {
|
||||||
// add cnt to avoid DmsCallbackThreadShmemInit to use UsedShmemSegAddr
|
// add cnt to avoid DmsCallbackThreadShmemInit to use UsedShmemSegAddr
|
||||||
(void)pg_atomic_add_fetch_u32(&g_instance.dms_cxt.inProcExitCnt, 1);
|
(void)pg_atomic_add_fetch_u32(&g_instance.dms_cxt.inProcExitCnt, 1);
|
||||||
@ -167,12 +165,15 @@ void proc_exit(int code)
|
|||||||
pg_usleep(WAIT_DMS_INIT_TIMEOUT);
|
pg_usleep(WAIT_DMS_INIT_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t_thrd.utils_cxt.backend_reserved) {
|
if (t_thrd.utils_cxt.backend_reserved) {
|
||||||
ereport(DEBUG2, (errmodule(MOD_MEM),
|
ereport(DEBUG2, (errmodule(MOD_MEM),
|
||||||
errmsg("[BackendReservedExit] current thread role is: %d, used memory is: %d MB\n",
|
errmsg("[BackendReservedExit] current thread role is: %d, used memory is: %d MB\n",
|
||||||
t_thrd.role, t_thrd.utils_cxt.trackedMemChunks)));
|
t_thrd.role, t_thrd.utils_cxt.trackedMemChunks)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AtEOXact_SysDBCache(false);
|
||||||
|
|
||||||
audit_processlogout_unified();
|
audit_processlogout_unified();
|
||||||
|
|
||||||
(void)pgstat_report_waitstatus(STATE_WAIT_UNDEFINED);
|
(void)pgstat_report_waitstatus(STATE_WAIT_UNDEFINED);
|
||||||
@ -324,22 +325,8 @@ void proc_exit(int code)
|
|||||||
if (t_thrd.postmaster_cxt.redirection_done)
|
if (t_thrd.postmaster_cxt.redirection_done)
|
||||||
ereport(LOG, (errmsg("Gaussdb exit(%d)", code)));
|
ereport(LOG, (errmsg("Gaussdb exit(%d)", code)));
|
||||||
|
|
||||||
while (file_list != NULL) {
|
/* release all library at proc exit. */
|
||||||
file_scanner = file_list;
|
internal_delete_library();
|
||||||
file_list = file_list->next;
|
|
||||||
#ifndef ENABLE_MEMORY_CHECK
|
|
||||||
/*
|
|
||||||
* in the senario of ImmediateShutdown, it is not safe to close plugin
|
|
||||||
* as PM thread will not wait for all children threads exist(will send SIGQUIT signal) referring to pmdie
|
|
||||||
*/
|
|
||||||
if (g_instance.status != ImmediateShutdown) {
|
|
||||||
(void)pg_dlclose(file_scanner->handle);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
pfree((char*)file_scanner);
|
|
||||||
file_scanner = NULL;
|
|
||||||
}
|
|
||||||
file_list = file_tail = NULL;
|
|
||||||
|
|
||||||
if (u_sess->attr.attr_resource.use_workload_manager)
|
if (u_sess->attr.attr_resource.use_workload_manager)
|
||||||
gscgroup_free();
|
gscgroup_free();
|
||||||
|
@ -483,6 +483,7 @@ extern Datum GetTypeZeroValue(Form_pg_attribute att_tup);
|
|||||||
extern Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot* slot);
|
extern Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot* slot);
|
||||||
|
|
||||||
extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone);
|
extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone);
|
||||||
|
extern int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace);
|
||||||
|
|
||||||
// AutoMutexLock
|
// AutoMutexLock
|
||||||
// Auto object for non-recursive pthread_mutex_t lock
|
// Auto object for non-recursive pthread_mutex_t lock
|
||||||
@ -491,7 +492,11 @@ class AutoMutexLock {
|
|||||||
public:
|
public:
|
||||||
AutoMutexLock(pthread_mutex_t* mutex, bool trace = true)
|
AutoMutexLock(pthread_mutex_t* mutex, bool trace = true)
|
||||||
: m_mutex(mutex), m_fLocked(false), m_trace(trace), m_owner(t_thrd.utils_cxt.CurrentResourceOwner)
|
: m_mutex(mutex), m_fLocked(false), m_trace(trace), m_owner(t_thrd.utils_cxt.CurrentResourceOwner)
|
||||||
{}
|
{
|
||||||
|
if (mutex == &file_list_lock) {
|
||||||
|
m_owner = t_thrd.lsc_cxt.local_sysdb_resowner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~AutoMutexLock()
|
~AutoMutexLock()
|
||||||
{
|
{
|
||||||
@ -538,10 +543,11 @@ public:
|
|||||||
if (m_fLocked) {
|
if (m_fLocked) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (t_thrd.utils_cxt.CurrentResourceOwner == NULL)
|
if (m_mutex == &file_list_lock) {
|
||||||
m_owner = NULL;
|
ret = ResourceOwnerForgetIfExistPthreadMutex(m_owner, m_mutex, m_trace);
|
||||||
|
} else {
|
||||||
ret = PthreadMutexUnlock(m_owner, m_mutex, m_trace);
|
ret = PthreadMutexUnlock(m_owner, m_mutex, m_trace);
|
||||||
|
}
|
||||||
m_fLocked = (ret == 0 ? false : true);
|
m_fLocked = (ret == 0 ? false : true);
|
||||||
if (m_fLocked) {
|
if (m_fLocked) {
|
||||||
/* this should never happen, system may be completely in a mess */
|
/* this should never happen, system may be completely in a mess */
|
||||||
|
@ -85,4 +85,6 @@ extern pthread_mutex_t gLocaleMutex;
|
|||||||
extern void CreateSharedMemoryAndSemaphores(bool makePrivate, int port);
|
extern void CreateSharedMemoryAndSemaphores(bool makePrivate, int port);
|
||||||
|
|
||||||
extern void cancelShmemExit(pg_on_exit_callback function, Datum arg);
|
extern void cancelShmemExit(pg_on_exit_callback function, Datum arg);
|
||||||
|
|
||||||
|
extern void internal_delete_library();
|
||||||
#endif /* IPC_H */
|
#endif /* IPC_H */
|
||||||
|
@ -153,7 +153,7 @@ extern void ResourceOwnerEnlargePthreadMutex(ResourceOwner owner);
|
|||||||
|
|
||||||
extern void PrintPthreadMutexLeakWarning(pthread_mutex_t* pMutex);
|
extern void PrintPthreadMutexLeakWarning(pthread_mutex_t* pMutex);
|
||||||
extern void PrintResourceOwnerLeakWarning();
|
extern void PrintResourceOwnerLeakWarning();
|
||||||
extern void ResourceOwnerReleasePthreadMutex();
|
extern void ResourceOwnerReleaseAllXactPthreadMutex();
|
||||||
|
|
||||||
extern void ResourceOwnerEnlargePartitionMapRefs(ResourceOwner owner);
|
extern void ResourceOwnerEnlargePartitionMapRefs(ResourceOwner owner);
|
||||||
extern void ResourceOwnerRememberPartitionMapRef(ResourceOwner owner, PartitionMap* partmap);
|
extern void ResourceOwnerRememberPartitionMapRef(ResourceOwner owner, PartitionMap* partmap);
|
||||||
@ -197,6 +197,7 @@ extern void ResourceOwnerEnlargeGlobalIsExclusive(ResourceOwner owner);
|
|||||||
extern void ResourceOwnerRememberGlobalIsExclusive(ResourceOwner owner, volatile uint32 *isexclusive);
|
extern void ResourceOwnerRememberGlobalIsExclusive(ResourceOwner owner, volatile uint32 *isexclusive);
|
||||||
extern void ResourceOwnerForgetGlobalIsExclusive(ResourceOwner owner, volatile uint32 *isexclusive);
|
extern void ResourceOwnerForgetGlobalIsExclusive(ResourceOwner owner, volatile uint32 *isexclusive);
|
||||||
|
|
||||||
|
extern void ResourceOwnerReleasePthreadMutex(ResourceOwner owner, bool isCommit);
|
||||||
extern void ResourceOwnerReleaseRWLock(ResourceOwner owner, bool isCommit);
|
extern void ResourceOwnerReleaseRWLock(ResourceOwner owner, bool isCommit);
|
||||||
extern void ResourceOwnerReleaseLocalCatCTup(ResourceOwner owner, bool isCommit);
|
extern void ResourceOwnerReleaseLocalCatCTup(ResourceOwner owner, bool isCommit);
|
||||||
extern void ResourceOwnerReleaseLocalCatCList(ResourceOwner owner, bool isCommit);
|
extern void ResourceOwnerReleaseLocalCatCList(ResourceOwner owner, bool isCommit);
|
||||||
|
@ -56,5 +56,6 @@ extern syscalllock env_lock;
|
|||||||
extern syscalllock dlerror_lock;
|
extern syscalllock dlerror_lock;
|
||||||
extern syscalllock kerberos_conn_lock;
|
extern syscalllock kerberos_conn_lock;
|
||||||
extern syscalllock read_cipher_lock;
|
extern syscalllock read_cipher_lock;
|
||||||
|
extern syscalllock file_list_lock;
|
||||||
|
|
||||||
#endif /* SYSCALL_LOCK_H_ */
|
#endif /* SYSCALL_LOCK_H_ */
|
||||||
|
Reference in New Issue
Block a user