pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Noah Misch <noah@leadboat.com>
To: Michael Paquier <michael@paquier.xyz>
Cc: Heikki Linnakangas <hlinnaka@iki.fi>
Cc: Tom Lane <tgl@sss.pgh.pa.us>
Cc: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: Re: Weird test mixup
Date: Wed, 1 May 2024 16:12:14 -0700
Message-ID: <20240501231214.40@rfd.leadboat.com> (raw)
In-Reply-To: <ZfTcZW1-Kh3fFLnZ@paquier.xyz>
References: <10fd6cdd-c5d9-46fe-9fa1-7e661191309e@iki.fi>
	<2387221.1710454778@sss.pgh.pa.us>
	<ZfOABU4ahF2QZQ6N@paquier.xyz>
	<2393552.1710458033@sss.pgh.pa.us>
	<ZfP7IDs9TvrKe49x@paquier.xyz>
	<e1a7ab78-1fa9-419c-b0d1-36d971bdf946@iki.fi>
	<ZfTcZW1-Kh3fFLnZ@paquier.xyz>

While writing an injection point test, I encountered a variant of the race
condition that f4083c4 fixed.  It had three sessions and this sequence of
events:

s1: local-attach to POINT
s2: enter InjectionPointRun(POINT), yield CPU just before injection_callback()
s3: detach POINT, deleting the InjectionPointCondition record
s2: wake up and run POINT as though it had been non-local

On Sat, Mar 16, 2024 at 08:40:21AM +0900, Michael Paquier wrote:
> On Fri, Mar 15, 2024 at 11:23:31AM +0200, Heikki Linnakangas wrote:
> > Wrt. the spinlock and shared memory handling, I think this would be simpler
> > if you could pass some payload in the InjectionPointAttach() call, which
> > would be passed back to the callback function:
> > 
> > In this case, the payload would be the "slot index" in shared memory.
> > 
> > Or perhaps always allocate, say, 1024 bytes of working area for every
> > attached injection point that the test module can use any way it wants. Like
> > for storing extra conditions, or for the wakeup counter stuff in
> > injection_wait(). A fixed size working area is a little crude, but would be
> > very handy in practice.

That would be one good way to solve it.  (Storing a slot index has the same
race condition, but it fixes the race to store a struct containing the PID.)

The best alternative I see is to keep an InjectionPointCondition forever after
creating it.  Give it a "bool valid" field that we set on detach.  I don't see
a major reason to prefer one of these over the other.  One puts a negligible
amount of memory pressure on the main segment, but it simplifies the module
code.  I lean toward the "1024 bytes of working area" idea.  Other ideas or
opinions?


Separately, injection_points_cleanup() breaks the rules by calling
InjectionPointDetach() while holding a spinlock.  The latter has an
elog(ERROR), and reaching that elog(ERROR) leaves a stuck spinlock.  I haven't
given as much thought to solutions for this one.

Thanks,
nm





view thread (52+ messages)  latest in thread

Message-ID: <20240501231214.40@rfd.leadboat.com>
Permalink:  ../20240501231214.40@rfd.leadboat.com/
Also on:    postgresql.org/message-id/20240501231214.40@rfd.leadboat.com

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: noah@leadboat.com, michael@paquier.xyz, hlinnaka@iki.fi, tgl@sss.pgh.pa.us
  Subject: Re: Weird test mixup
  In-Reply-To: <20240501231214.40@rfd.leadboat.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox