Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6f3820f

Browse files
committed
Fix race condition in TupleDescCompactAttr assert code
5983a4c added CompactAttribute as an abbreviated alternative toFormData_pg_attribute to allow more cache-friendly processing in tasksrelated to TupleDescs. That commit contained some assert-only code tocheck that the CompactAttribute had been populated correctly, however,the method used to do that checking caused the TupleDesc'sCompactAttribute to be zeroed before it was repopulated and compared tothe snapshot taken before the memset call. This caused issues as the typecache caches TupleDescs in shared memory which can be used by multiplebackend processes at the same time. There was a window of time betweenthe zero and repopulation of the CompactAttribute where another processwould mistakenly think that the CompactAttribute is invalid due to thememset.To fix this, instead of taking a snapshot of the CompactAttribute andcalling populate_compact_attribute() and comparing the snapshot to thefreshly populated TupleDesc's CompactAttribute, refactor things so wecan just populate a temporary CompactAttribute on the stack. This waywe don't touch the TupleDesc's memory.Reported-by: Alexander Lakhin, SQLsmithDiscussion:https://postgr.es/m/ca3a256a-5d12-42db-aabe-a75a030d9fb9@gmail.com
1 parent38da053 commit6f3820f

File tree

2 files changed

+69
-31
lines changed

2 files changed

+69
-31
lines changed

‎src/backend/access/common/tupdesc.c

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,13 @@ ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
5757
}
5858

5959
/*
60-
* populate_compact_attribute
61-
*Fill in the corresponding CompactAttribute element from the
62-
*Form_pg_attribute for the given attribute number. This must be called
63-
*whenever a change is made to a Form_pg_attribute in the TupleDesc.
60+
* populate_compact_attribute_internal
61+
*Helper function for populate_compact_attribute()
6462
*/
65-
void
66-
populate_compact_attribute(TupleDesctupdesc,intattnum)
63+
staticinlinevoid
64+
populate_compact_attribute_internal(Form_pg_attributesrc,
65+
CompactAttribute*dst)
6766
{
68-
Form_pg_attributesrc=TupleDescAttr(tupdesc,attnum);
69-
CompactAttribute*dst=&tupdesc->compact_attrs[attnum];
70-
7167
memset(dst,0,sizeof(CompactAttribute));
7268

7369
dst->attcacheoff=-1;
@@ -101,6 +97,63 @@ populate_compact_attribute(TupleDesc tupdesc, int attnum)
10197
}
10298
}
10399

100+
/*
101+
* populate_compact_attribute
102+
*Fill in the corresponding CompactAttribute element from the
103+
*Form_pg_attribute for the given attribute number. This must be called
104+
*whenever a change is made to a Form_pg_attribute in the TupleDesc.
105+
*/
106+
void
107+
populate_compact_attribute(TupleDesctupdesc,intattnum)
108+
{
109+
Form_pg_attributesrc=TupleDescAttr(tupdesc,attnum);
110+
CompactAttribute*dst;
111+
112+
/*
113+
* Don't use TupleDescCompactAttr to prevent infinite recursion in assert
114+
* builds.
115+
*/
116+
dst=&tupdesc->compact_attrs[attnum];
117+
118+
populate_compact_attribute_internal(src,dst);
119+
}
120+
121+
#ifdefUSE_ASSERT_CHECKING
122+
/*
123+
* verify_compact_attribute
124+
*In Assert enabled builds, we verify that the CompactAttribute is
125+
*populated correctly. This helps find bugs in places such as ALTER
126+
*TABLE where code makes changes to the FormData_pg_attribute but
127+
*forgets to call populate_compact_attribute().
128+
*
129+
* This is used in TupleDescCompactAttr(), but declared here to allow access
130+
* to populate_compact_attribute_internal().
131+
*/
132+
void
133+
verify_compact_attribute(TupleDesctupdesc,intattnum)
134+
{
135+
CompactAttribute*cattr=&tupdesc->compact_attrs[attnum];
136+
Form_pg_attributeattr=TupleDescAttr(tupdesc,attnum);
137+
CompactAttributetmp;
138+
139+
/*
140+
* Populate the temporary CompactAttribute from the corresponding
141+
* Form_pg_attribute
142+
*/
143+
populate_compact_attribute_internal(attr,&tmp);
144+
145+
/*
146+
* Make the attcacheoff match since it's been reset to -1 by
147+
* populate_compact_attribute_internal.
148+
*/
149+
tmp.attcacheoff=cattr->attcacheoff;
150+
151+
/* Check the freshly populated CompactAttribute matches the TupleDesc's */
152+
Assert(memcmp(&tmp,cattr,sizeof(CompactAttribute))==0);
153+
}
154+
#endif
155+
156+
104157
/*
105158
* CreateTemplateTupleDesc
106159
*This function allocates an empty tuple descriptor structure.

‎src/include/access/tupdesc.h

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -158,37 +158,22 @@ TupleDescAttr(TupleDesc tupdesc, int i)
158158

159159
#undef TupleDescAttrAddress
160160

161+
#ifdefUSE_ASSERT_CHECKING
162+
externvoidverify_compact_attribute(TupleDesc,intattnum);
163+
#endif
164+
161165
/*
162166
* Accessor for the i'th CompactAttribute element of tupdesc.
163167
*/
164168
staticinlineCompactAttribute*
165169
TupleDescCompactAttr(TupleDesctupdesc,inti)
166170
{
167171
CompactAttribute*cattr=&tupdesc->compact_attrs[i];
168-
#ifdefUSE_ASSERT_CHECKING
169-
CompactAttributesnapshot;
170172

171-
/*
172-
* In Assert enabled builds we verify that the CompactAttribute is
173-
* populated correctly. This helps find bugs in places such as ALTER
174-
* TABLE where code makes changes to the FormData_pg_attribute but forgets
175-
* to call populate_compact_attribute.
176-
*/
177-
178-
/*
179-
* Take a snapshot of how the CompactAttribute is now before calling
180-
* populate_compact_attribute to make it up-to-date with the
181-
* FormData_pg_attribute.
182-
*/
183-
memcpy(&snapshot,cattr,sizeof(CompactAttribute));
184-
185-
populate_compact_attribute(tupdesc,i);
186-
187-
/* reset attcacheoff back to what it was */
188-
cattr->attcacheoff=snapshot.attcacheoff;
173+
#ifdefUSE_ASSERT_CHECKING
189174

190-
/*Ensurethesnapshot matches the freshlypopulated CompactAttribute */
191-
Assert(memcmp(&snapshot,cattr,sizeof(CompactAttribute))==0);
175+
/*Check thattheCompactAttribute is correctlypopulated */
176+
verify_compact_attribute(tupdesc,i);
192177
#endif
193178

194179
returncattr;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp