Fix race in Parallel Hash Join batch cleanup.
authorThomas Munro <tmunro@postgresql.org>
Wed, 17 Mar 2021 04:46:39 +0000 (17:46 +1300)
committerThomas Munro <tmunro@postgresql.org>
Wed, 17 Mar 2021 05:10:17 +0000 (18:10 +1300)
commit0129c56fbe5c26bfec91bfc2c8a3b8818f441d6e
treec142ce9d15161f31de637b9c5202eb7a27e8e58d
parenta2764d87df0475c786d021f4cd553aff2ae5f5bf
Fix race in Parallel Hash Join batch cleanup.

With very unlucky timing and parallel_leader_participation off, PHJ
could attempt to access per-batch state just as it was being freed.
There was code intended to prevent that by checking for a cleared
pointer, but it was buggy.

Fix, by introducing an extra barrier phase.  The new phase
PHJ_BUILD_RUNNING means that it's safe to access the per-batch state to
find a batch to help with, and PHJ_BUILD_DONE means that it is too late.
The last to detach will free the array of per-batch state as before, but
now it will also atomically advance the phase at the same time, so that
late attachers can avoid the hazard, without the data race.  This
mirrors the way per-batch hash tables are freed (see phases
PHJ_BATCH_PROBING and PHJ_BATCH_DONE).

Revealed by a one-off build farm failure, where BarrierAttach() failed a
sanity check assertion, because the memory had been clobbered by
dsa_free().

Back-patch to 11, where the code arrived.

Reported-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/20200929061142.GA29096%40paquier.xyz
src/backend/executor/nodeHash.c
src/backend/executor/nodeHashjoin.c
src/include/executor/hashjoin.h