PG-325: Fix deadlock.
If a query exceeds pg_stat_monitor.pgsm_query_max_len, then it's truncated before we save it into the query buffer (SaveQueryText). When reading the query back, on pg_stat_monitor_internal, we allocate a buffer for the query with length = pg_stat_monitor.pgsm_query_max_len, the problem is that the read_query function adds a '\0' to the end of the buffer when reading a query, thus if a query has been truncated, for example, to 1024, when reading it back read_query will store the '\0' at the position 1025, an out of array bounds position. Then, when we call pfree to release the buffer, PostgreSQL notices the buffer overrun and triggers an error assertion, the assertion calls our error hook which attempts to acquire the shared pgss->lock before pg_stat_monitor_internal has released it, leading to a deadlock. To avoid the problem we add 1 more byte to the extra '\0' during palloc call for query_text and parent_query_text. Also, we release the lock before calling pfree, just in case PostgreSQL finds a problem in pfree we won't deadlock again and get the error reported correctly.pull/184/head
parent
24ae3fa66f
commit
9f8f94ed9c
|
@ -1701,8 +1701,8 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
char parentid_txt[32];
|
||||
pgssSharedState *pgss = pgsm_get_ss();
|
||||
HTAB *pgss_hash = pgsm_get_hash();
|
||||
char *query_txt = (char*) palloc0(PGSM_QUERY_MAX_LEN);
|
||||
char *parent_query_txt = (char*) palloc0(PGSM_QUERY_MAX_LEN);
|
||||
char *query_txt = (char*) palloc0(PGSM_QUERY_MAX_LEN + 1);
|
||||
char *parent_query_txt = (char*) palloc0(PGSM_QUERY_MAX_LEN + 1);
|
||||
|
||||
/* Safety check... */
|
||||
if (!IsSystemInitialized())
|
||||
|
@ -2048,11 +2048,12 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
values[i++] = BoolGetDatum(toplevel);
|
||||
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
||||
}
|
||||
pfree(query_txt);
|
||||
pfree(parent_query_txt);
|
||||
/* clean up and return the tuplestore */
|
||||
LWLockRelease(pgss->lock);
|
||||
|
||||
pfree(query_txt);
|
||||
pfree(parent_query_txt);
|
||||
|
||||
tuplestore_donestoring(tupstore);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue