Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
74aaa213
Commit
74aaa213
authored
May 19, 2011
by
Robert Haas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix race condition in CheckTargetForConflictsIn.
Dan Ports
parent
6b449d90
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
79 additions
and
128 deletions
+79
-128
src/backend/storage/lmgr/predicate.c
src/backend/storage/lmgr/predicate.c
+79
-128
No files found.
src/backend/storage/lmgr/predicate.c
View file @
74aaa213
...
@@ -3638,6 +3638,8 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
...
@@ -3638,6 +3638,8 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
LWLockId
partitionLock
;
LWLockId
partitionLock
;
PREDICATELOCKTARGET
*
target
;
PREDICATELOCKTARGET
*
target
;
PREDICATELOCK
*
predlock
;
PREDICATELOCK
*
predlock
;
PREDICATELOCK
*
mypredlock
=
NULL
;
PREDICATELOCKTAG
mypredlocktag
;
Assert
(
MySerializableXact
!=
InvalidSerializableXact
);
Assert
(
MySerializableXact
!=
InvalidSerializableXact
);
...
@@ -3683,139 +3685,21 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
...
@@ -3683,139 +3685,21 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
if
(
sxact
==
MySerializableXact
)
if
(
sxact
==
MySerializableXact
)
{
{
/*
/*
* If we're getting a write lock on
the tuple and we're not in a
* If we're getting a write lock on
a tuple, we don't need
*
subtransaction, we don't need a predicate (SIREAD) lock. We
*
a predicate (SIREAD) lock on the same tuple. We can
*
can't use this optimization within a subtransaction because the
*
safely remove our SIREAD lock, but we'll defer doing so
*
subtransaction could be rolled back, and we would be left
*
until after the loop because that requires upgrading to
*
without any lock at the top level
.
*
an exclusive partition lock
.
*
*
* At this point our transaction already has an ExclusiveRowLock
* We can't use this optimization within a subtransaction
* on the relation, so we are OK to drop the predicate lock on the
* because the subtransaction could roll back, and we
* tuple, if found, without fearing that another write against the
* would be left without any lock at the top level.
* tuple will occur before the MVCC information makes it to the
* buffer.
*/
*/
if
(
!
IsSubTransaction
()
if
(
!
IsSubTransaction
()
&&
GET_PREDICATELOCKTARGETTAG_OFFSET
(
*
targettag
))
&&
GET_PREDICATELOCKTARGETTAG_OFFSET
(
*
targettag
))
{
{
uint32
predlockhashcode
;
mypredlock
=
predlock
;
PREDICATELOCKTARGET
*
rmtarget
=
NULL
;
mypredlocktag
=
predlock
->
tag
;
PREDICATELOCK
*
rmpredlock
;
LOCALPREDICATELOCK
*
locallock
,
*
rmlocallock
;
/*
* This is a tuple on which we have a tuple predicate lock. We
* only have shared LW locks now; release those, and get
* exclusive locks only while we modify things.
*/
LWLockRelease
(
SerializableXactHashLock
);
LWLockRelease
(
partitionLock
);
LWLockAcquire
(
SerializablePredicateLockListLock
,
LW_SHARED
);
LWLockAcquire
(
partitionLock
,
LW_EXCLUSIVE
);
LWLockAcquire
(
SerializableXactHashLock
,
LW_EXCLUSIVE
);
/*
* Remove the predicate lock from shared memory, if it wasn't
* removed while the locks were released. One way that could
* happen is from autovacuum cleaning up an index.
*/
predlockhashcode
=
PredicateLockHashCodeFromTargetHashCode
(
&
(
predlock
->
tag
),
targettaghash
);
rmpredlock
=
(
PREDICATELOCK
*
)
hash_search_with_hash_value
(
PredicateLockHash
,
&
(
predlock
->
tag
),
predlockhashcode
,
HASH_FIND
,
NULL
);
if
(
rmpredlock
)
{
Assert
(
rmpredlock
==
predlock
);
SHMQueueDelete
(
predlocktargetlink
);
SHMQueueDelete
(
&
(
predlock
->
xactLink
));
rmpredlock
=
(
PREDICATELOCK
*
)
hash_search_with_hash_value
(
PredicateLockHash
,
&
(
predlock
->
tag
),
predlockhashcode
,
HASH_REMOVE
,
NULL
);
Assert
(
rmpredlock
==
predlock
);
RemoveTargetIfNoLongerUsed
(
target
,
targettaghash
);
LWLockRelease
(
SerializableXactHashLock
);
LWLockRelease
(
partitionLock
);
LWLockRelease
(
SerializablePredicateLockListLock
);
locallock
=
(
LOCALPREDICATELOCK
*
)
hash_search_with_hash_value
(
LocalPredicateLockHash
,
targettag
,
targettaghash
,
HASH_FIND
,
NULL
);
/*
* Remove entry in local lock table if it exists and has
* no children. It's OK if it doesn't exist; that means
* the lock was transferred to a new target by a different
* backend.
*/
if
(
locallock
!=
NULL
)
{
locallock
->
held
=
false
;
if
(
locallock
->
childLocks
==
0
)
{
rmlocallock
=
(
LOCALPREDICATELOCK
*
)
hash_search_with_hash_value
(
LocalPredicateLockHash
,
targettag
,
targettaghash
,
HASH_REMOVE
,
NULL
);
Assert
(
rmlocallock
==
locallock
);
}
}
DecrementParentLocks
(
targettag
);
/*
* If we've cleaned up the last of the predicate locks for
* the target, bail out before re-acquiring the locks.
*/
if
(
rmtarget
)
return
;
/*
* The list has been altered. Start over at the front.
*/
LWLockAcquire
(
partitionLock
,
LW_SHARED
);
nextpredlock
=
(
PREDICATELOCK
*
)
SHMQueueNext
(
&
(
target
->
predicateLocks
),
&
(
target
->
predicateLocks
),
offsetof
(
PREDICATELOCK
,
targetLink
));
LWLockAcquire
(
SerializableXactHashLock
,
LW_SHARED
);
}
else
{
/*
* The predicate lock was cleared while we were attempting
* to upgrade our lightweight locks. Revert to the shared
* locks.
*/
LWLockRelease
(
SerializableXactHashLock
);
LWLockRelease
(
partitionLock
);
LWLockRelease
(
SerializablePredicateLockListLock
);
LWLockAcquire
(
partitionLock
,
LW_SHARED
);
/*
* The list may have been altered by another process while
* we weren't holding the partition lock. Start over at
* the front.
*/
nextpredlock
=
(
PREDICATELOCK
*
)
SHMQueueNext
(
&
(
target
->
predicateLocks
),
&
(
target
->
predicateLocks
),
offsetof
(
PREDICATELOCK
,
targetLink
));
LWLockAcquire
(
SerializableXactHashLock
,
LW_SHARED
);
}
}
}
}
}
else
if
(
!
SxactIsRolledBack
(
sxact
)
else
if
(
!
SxactIsRolledBack
(
sxact
)
...
@@ -3849,6 +3733,73 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
...
@@ -3849,6 +3733,73 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
}
}
LWLockRelease
(
SerializableXactHashLock
);
LWLockRelease
(
SerializableXactHashLock
);
LWLockRelease
(
partitionLock
);
LWLockRelease
(
partitionLock
);
/*
* If we found one of our own SIREAD locks to remove, remove it
* now.
*
* At this point our transaction already has an ExclusiveRowLock
* on the relation, so we are OK to drop the predicate lock on the
* tuple, if found, without fearing that another write against the
* tuple will occur before the MVCC information makes it to the
* buffer.
*/
if
(
mypredlock
!=
NULL
)
{
uint32
predlockhashcode
;
PREDICATELOCK
*
rmpredlock
;
LWLockAcquire
(
SerializablePredicateLockListLock
,
LW_SHARED
);
LWLockAcquire
(
partitionLock
,
LW_EXCLUSIVE
);
LWLockAcquire
(
SerializableXactHashLock
,
LW_EXCLUSIVE
);
/*
* Remove the predicate lock from shared memory, if it wasn't
* removed while the locks were released. One way that could
* happen is from autovacuum cleaning up an index.
*/
predlockhashcode
=
PredicateLockHashCodeFromTargetHashCode
(
&
mypredlocktag
,
targettaghash
);
rmpredlock
=
(
PREDICATELOCK
*
)
hash_search_with_hash_value
(
PredicateLockHash
,
&
mypredlocktag
,
predlockhashcode
,
HASH_FIND
,
NULL
);
if
(
rmpredlock
!=
NULL
)
{
Assert
(
rmpredlock
==
mypredlock
);
SHMQueueDelete
(
&
(
mypredlock
->
targetLink
));
SHMQueueDelete
(
&
(
mypredlock
->
xactLink
));
rmpredlock
=
(
PREDICATELOCK
*
)
hash_search_with_hash_value
(
PredicateLockHash
,
&
mypredlocktag
,
predlockhashcode
,
HASH_REMOVE
,
NULL
);
Assert
(
rmpredlock
==
mypredlock
);
RemoveTargetIfNoLongerUsed
(
target
,
targettaghash
);
}
LWLockRelease
(
SerializableXactHashLock
);
LWLockRelease
(
partitionLock
);
LWLockRelease
(
SerializablePredicateLockListLock
);
if
(
rmpredlock
!=
NULL
)
{
/*
* Remove entry in local lock table if it exists. It's OK
* if it doesn't exist; that means the lock was
* transferred to a new target by a different backend.
*/
hash_search_with_hash_value
(
LocalPredicateLockHash
,
targettag
,
targettaghash
,
HASH_REMOVE
,
NULL
);
DecrementParentLocks
(
targettag
);
}
}
}
}
/*
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment