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

Commitf38903d

Browse files
committed
Remove race condition in pg_get_expr().
Since its introduction, pg_get_expr() has intended to silentlyreturn NULL if called with an invalid relation OID, as can happenwhen scanning the catalogs concurrently with relation drops.However, there is a race condition: we check validity of the OIDat the start, but it could get dropped just afterward, leading tofailures. This is the cause of some intermittent instability we'reseeing in a proposed new test case, and presumably it's a hazard inthe field as well.We can fix this by AccessShareLock-ing the target relation for theduration of pg_get_expr(). Since we don't require any permissionson the target relation, this is semantically a bit undesirable. Butit turns out that the set_relation_column_names() subroutine alreadytakes a transient AccessShareLock on that relation, and has done sincecommit2ffa740 in 2012. Given the lack of complaints about that, itseems like there should be no harm in holding the lock a bit longer.Back-patch to all supported branches.Discussion:https://postgr.es/m/31ddcc01-a71b-4e8c-9948-01d1c47293ca@eisentraut.org
1 parent9fb1396 commitf38903d

File tree

1 file changed

+33
-35
lines changed

1 file changed

+33
-35
lines changed

‎src/backend/utils/adt/ruleutils.c‎

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,7 @@ static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
330330
boolattrsOnly,boolmissing_ok);
331331
staticchar*pg_get_constraintdef_worker(OidconstraintId,boolfullCommand,
332332
intprettyFlags,boolmissing_ok);
333-
statictext*pg_get_expr_worker(text*expr,Oidrelid,constchar*relname,
334-
intprettyFlags);
333+
statictext*pg_get_expr_worker(text*expr,Oidrelid,intprettyFlags);
335334
staticintprint_function_arguments(StringInfobuf,HeapTupleproctup,
336335
boolprint_table_args,boolprint_defaults);
337336
staticvoidprint_function_rettype(StringInfobuf,HeapTupleproctup);
@@ -2360,36 +2359,28 @@ decompile_column_index_array(Datum column_index_array, Oid relId,
23602359
* the one specified by the second parameter. This is sufficient for
23612360
* partial indexes, column default expressions, etc. We also support
23622361
* Var-free expressions, for which the OID can be InvalidOid.
2362+
*
2363+
* If the OID is nonzero but not actually valid, don't throw an error,
2364+
* just return NULL. This is a bit questionable, but it's what we've
2365+
* done historically, and it can help avoid unwanted failures when
2366+
* examining catalog entries for just-deleted relations.
23632367
* ----------
23642368
*/
23652369
Datum
23662370
pg_get_expr(PG_FUNCTION_ARGS)
23672371
{
23682372
text*expr=PG_GETARG_TEXT_PP(0);
23692373
Oidrelid=PG_GETARG_OID(1);
2374+
text*result;
23702375
intprettyFlags;
2371-
char*relname;
23722376

23732377
prettyFlags=PRETTYFLAG_INDENT;
23742378

2375-
if (OidIsValid(relid))
2376-
{
2377-
/* Get the name for the relation */
2378-
relname=get_rel_name(relid);
2379-
2380-
/*
2381-
* If the OID isn't actually valid, don't throw an error, just return
2382-
* NULL. This is a bit questionable, but it's what we've done
2383-
* historically, and it can help avoid unwanted failures when
2384-
* examining catalog entries for just-deleted relations.
2385-
*/
2386-
if (relname==NULL)
2387-
PG_RETURN_NULL();
2388-
}
2379+
result=pg_get_expr_worker(expr,relid,prettyFlags);
2380+
if (result)
2381+
PG_RETURN_TEXT_P(result);
23892382
else
2390-
relname=NULL;
2391-
2392-
PG_RETURN_TEXT_P(pg_get_expr_worker(expr,relid,relname,prettyFlags));
2383+
PG_RETURN_NULL();
23932384
}
23942385

23952386
Datum
@@ -2398,31 +2389,25 @@ pg_get_expr_ext(PG_FUNCTION_ARGS)
23982389
text*expr=PG_GETARG_TEXT_PP(0);
23992390
Oidrelid=PG_GETARG_OID(1);
24002391
boolpretty=PG_GETARG_BOOL(2);
2392+
text*result;
24012393
intprettyFlags;
2402-
char*relname;
24032394

24042395
prettyFlags=pretty ? (PRETTYFLAG_PAREN |PRETTYFLAG_INDENT |PRETTYFLAG_SCHEMA) :PRETTYFLAG_INDENT;
24052396

2406-
if (OidIsValid(relid))
2407-
{
2408-
/* Get the name for the relation */
2409-
relname=get_rel_name(relid);
2410-
/* See notes above */
2411-
if (relname==NULL)
2412-
PG_RETURN_NULL();
2413-
}
2397+
result=pg_get_expr_worker(expr,relid,prettyFlags);
2398+
if (result)
2399+
PG_RETURN_TEXT_P(result);
24142400
else
2415-
relname=NULL;
2416-
2417-
PG_RETURN_TEXT_P(pg_get_expr_worker(expr,relid,relname,prettyFlags));
2401+
PG_RETURN_NULL();
24182402
}
24192403

24202404
statictext*
2421-
pg_get_expr_worker(text*expr,Oidrelid,constchar*relname,intprettyFlags)
2405+
pg_get_expr_worker(text*expr,Oidrelid,intprettyFlags)
24222406
{
24232407
Node*node;
24242408
List*context;
24252409
char*exprstr;
2410+
Relationrel=NULL;
24262411
char*str;
24272412

24282413
/* Convert input TEXT object to C string */
@@ -2433,16 +2418,29 @@ pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
24332418

24342419
pfree(exprstr);
24352420

2436-
/* Prepare deparse context if needed */
2421+
/*
2422+
* Prepare deparse context if needed. If we are deparsing with a relid,
2423+
* we need to transiently open and lock the rel, to make sure it won't go
2424+
* away underneath us. (set_relation_column_names would lock it anyway,
2425+
* so this isn't really introducing any new behavior.)
2426+
*/
24372427
if (OidIsValid(relid))
2438-
context=deparse_context_for(relname,relid);
2428+
{
2429+
rel=try_relation_open(relid,AccessShareLock);
2430+
if (rel==NULL)
2431+
returnNULL;
2432+
context=deparse_context_for(RelationGetRelationName(rel),relid);
2433+
}
24392434
else
24402435
context=NIL;
24412436

24422437
/* Deparse */
24432438
str=deparse_expression_pretty(node,context, false, false,
24442439
prettyFlags,0);
24452440

2441+
if (rel!=NULL)
2442+
relation_close(rel,AccessShareLock);
2443+
24462444
returnstring_to_text(str);
24472445
}
24482446

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp