Re: [PATCHES] New shared memory hooks proposal (was Re:

From: Marc Munro <marc(at)bloodnok(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: [PATCHES] New shared memory hooks proposal (was Re:
Date: 2006-10-15 19:57:39
Message-ID: 1160942259.3937.16.camel@bloodnok.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches

On Sat, 2006-10-14 at 14:55 -0400, Tom Lane wrote:
> Marc Munro <marc(at)bloodnok(dot)com> writes:
> > The attached patch provides add-ins with the means to register for
> > shared memory and LWLocks.
>
> I finally got around to reviewing this patch, and realized that it's got
> a pretty fundamental design flaw: it isn't useful under Windows (or any
> other EXEC_BACKEND platform), because there isn't any provision for
> backends to locate structs allocated by other backends by means of
> searching in shared memory. AFAICS the code can only do something
> useful in a platform where allocations made in the postmaster process
> can be found by backends via fork inheritance of pointers.

Rats! You are right. I had quite overlooked the windows case.

> The right way to handle shmem allocations is to use ShmemInitStruct
> to either allocate a shared struct for the first time or attach to a
> previously made instance of the struct. (This "struct" could be a
> memory allocation arena itself, but that's not the core code's problem.)
> Now we could extend the patch so that each "addin" has its own
> ShmemIndex within its private workspace, but I think that's probably
> overkill. My inclination is to rip out ShmemAllocFromContext and expect
> addins to use ShmemInitStruct the same as everyone else. The hook
> callable at shared_preload_libraries time should just serve to add
> the necessary amount to the computed size of the shared memory segment.

I think that works for me.

> RegisterAddinLWLock is broken in the same way: it could only be used
> safely if the registered lock ID were remembered in shared memory,
> but since shared memory doesn't exist at the time it's supposed to be
> called, there's no way to do that. Again, it'd seem to work as long as
> the lock ID value were inherited via fork, but that's gonna fail on
> EXEC_BACKEND builds. I think we should probably take this out in favor
> of something that just increments a counter that replaces
> NUM_USER_DEFINED_LWLOCKS, and expect people to use LWLockAssign() at an
> appropriate time while initializing their shared memory areas.

Agreed.

> It strikes me that there's a race condition here, which we've not seen
> in previous use because backends expect all standard shared memory
> structs to have already been initialized by the postmaster. An add-on
> will instead have to operate under the regime of "first backend wanting
> to use the struct must init it". Although ShmemInitStruct returns a
> "found" bool telling you you've got to init it, there's no interlock
> ensuring that you can do so before someone else comes along and tries to
> use the struct (which he'll assume is done because he sees found = true).
> And, per above discussion, an add-on can't solve this for itself using
> an add-on LWLock, because it really has to acquire its add-on locks
> while initializing that same shmem struct, which is where it's going to
> keep the locks' identity :-(
>
> So I think we need to provide a standard LWLock reserved for the purpose
> of synchronizing first-time use of a shmem struct. The coding rules for
> an add-on would then look like:
>
> * in the shared_preload_libraries hook:
>
> RequestAddinShmemSpace(size);
> RequestAddinLWLocks(n);
>
> * in a backend, to access a shared memory struct:
>
> static mystruct *ptr = NULL;
>
> if (!ptr)
> {
> bool found;
>
> LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
> ptr = ShmemInitStruct("my struct name", size, &found);
> if (!ptr)
> elog(ERROR, "out of shared memory");
> if (!found)
> {
> initialize contents of shmem area;
> acquire any requested LWLocks using:
> ptr->mylockid = LWLockAssign();
> }
> LWLockRelease(AddinShmemInitLock);
> }
>
>
> Thoughts?

I am content that what you suggest is the right way to go. I will work
on a new patch immediately, unless you would prefer to do this yourself.

It seems to me that these coding rules should be documented in the main
documentation, I guess in the section that describes Dynamic Loading.
Would you like me to take a stab at that?

__
Marc

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message David Fetter 2006-10-15 20:10:54 Re: BUG #2683: spi_exec_query in plperl returns column names which are not marked as UTF8
Previous Message Tom Lane 2006-10-15 19:55:08 Re: Postgresql Caching

Browse pgsql-patches by date

  From Date Subject
Next Message Tom Lane 2006-10-15 20:36:10 Re: [PATCHES] New shared memory hooks proposal (was Re: pre_load_libraries)
Previous Message Simon Riggs 2006-10-15 16:22:33 Re: index advisor