Skip to content

Commit 843d90d

Browse files
committed
Fix session lock leak in ALTER DATABASE SET TABLESPACE for utility mode
movedb() acquires a session-level AccessExclusiveLock on the database via MoveDbSessionLockAcquire(). The release in CommitTransaction() only checked for GP_ROLE_DISPATCH and IS_SINGLENODE(), missing GP_ROLE_UTILITY. This caused the lock to leak in standalone backends (e.g. TAP tests), triggering a proc.c assertion failure at exit: FailedAssertion("SHMQueueEmpty(&(MyProc->myProcLocks[i]))") Add GP_ROLE_UTILITY to the release condition. Also fix a spurious "could not read symbolic link" log message when dropping in-place tablespaces: readlink() on a directory returns EINVAL, which is expected and can be safely skipped. Fixes #1626
1 parent e91712d commit 843d90d

File tree

2 files changed

+19
-12
lines changed

2 files changed

+19
-12
lines changed

src/backend/access/transam/xact.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,13 +3036,15 @@ CommitTransaction(void)
30363036
DoPendingDbDeletes(true);
30373037

30383038
/*
3039-
* Only QD holds the session level lock this long for a movedb operation.
3040-
* This is to prevent another transaction from moving database objects into
3041-
* the source database oid directory while it is being deleted. We don't
3042-
* worry about aborts as we release session level locks automatically during
3043-
* an abort as opposed to a commit.
3044-
*/
3045-
if(Gp_role == GP_ROLE_DISPATCH || IS_SINGLENODE())
3039+
* Release the session level lock held for a movedb operation. This is to
3040+
* prevent another transaction from moving database objects into the source
3041+
* database oid directory while it is being deleted. We don't worry about
3042+
* aborts as we release session level locks automatically during an abort
3043+
* as opposed to a commit. We must also release in utility mode (e.g.
3044+
* standalone backends used in TAP tests).
3045+
*/
3046+
if (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_UTILITY ||
3047+
IS_SINGLENODE())
30463048
MoveDbSessionLockRelease();
30473049

30483050
/*

src/backend/commands/tablespace.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,14 +1230,19 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
12301230
linkloc = pstrdup(linkloc_with_version_dir);
12311231
get_parent_directory(linkloc);
12321232

1233-
/* Remove the symlink target directory if it exists or is valid. */
1233+
/*
1234+
* Remove the symlink target directory if it exists or is valid.
1235+
* If linkloc is a directory (e.g. in-place tablespace), readlink()
1236+
* will fail with EINVAL, which we can safely skip.
1237+
*/
12341238
rllen = readlink(linkloc, link_target_dir, sizeof(link_target_dir));
12351239
if(rllen < 0)
12361240
{
1237-
ereport(redo ? LOG : ERROR,
1238-
(errcode_for_file_access(),
1239-
errmsg("could not read symbolic link \"%s\": %m",
1240-
linkloc)));
1241+
if (errno != EINVAL)
1242+
ereport(redo ? LOG : ERROR,
1243+
(errcode_for_file_access(),
1244+
errmsg("could not read symbolic link \"%s\": %m",
1245+
linkloc)));
12411246
}
12421247
else if(rllen >= sizeof(link_target_dir))
12431248
{

0 commit comments

Comments
 (0)