Re: [HACKERS] Regarding Postgres Dynamic Shared Memory (DSA) - Mailing list pgsql-hackers

From Thomas Munro
Subject Re: [HACKERS] Regarding Postgres Dynamic Shared Memory (DSA)
Date
Msg-id CAEepm=1ryxmhsLYT=7EasgAH7uyeo4493tob1W=x6buN1DYfJQ@mail.gmail.com
Whole thread Raw
In response to Re: [HACKERS] Regarding Postgres Dynamic Shared Memory (DSA)  (Mahi Gurram <teckymahi@gmail.com>)
Responses Re: [HACKERS] Regarding Postgres Dynamic Shared Memory (DSA)
List pgsql-hackers
On Thu, Jun 15, 2017 at 6:32 PM, Mahi Gurram <teckymahi@gmail.com> wrote:
> Followed the same as per your suggestion. Refer the code snippet below:
>
>> void
>> _PG_init(void){
>> RequestAddinShmemSpace(100000000);
>>         PreviousShmemHook = shmem_startup_hook;
>>        shmem_startup_hook = BufferShmemHook;
>> }
>> void BufferShmemHook(){
>> dsa_area *area;
>> dsa_pointer data_ptr;
>>         char *mem;
>>   area = dsa_create(my_tranche_id());
>>        data_ptr = dsa_allocate(area, 42);
>>        mem = (char *) dsa_get_address(area, data_ptr);
>>        if (mem != NULL){
>>            snprintf(mem, 42, "Hello world");
>>        }
>>         bool found;
>> shmemData = ShmemInitStruct("Mahi_Shared_Data",
>>   sizeof(shared_data),
>>   &found);
>> shmemData->shared_area = area;
>> shmemData->shared_area_handle = dsa_get_handle(area);
>> shmemData->shared_data_ptr = data_ptr;
>>         shmemData->head=NULL;
>> }
>
>
> Wrote one UDF function, which is called by one of the client connection and
> that tries to use the same dsa. But unfortunately it is behaving strange.
>
> First call to my UDF function is throwing segmentation fault and postgres is
> quitting and auto restarting. If i try calling the same UDF function again
> in new connection(after postgres restart) it is working fine.
>
> Put some prints in postgres source code and found that dsa_allocate() is
> trying to use area->control(dsa_area_control object) which is pointing to
> wrong address but after restarting it is pointing to right address and hence
> it is working fine after restart.
>
> I'm totally confused and stuck at this point. Please help me in solving
> this.
>
> PS: It is working fine in Mac.. in only linux systems i'm facing this
> behaviour.
>
> I have attached the zip of my extension code along with screenshot of the
> pgclient and log file with debug prints for better understanding.
> *logfile is edited for providing some comments for better understanding.
>
> Please help me in solving this.

Hi Mahi

I didn't try your code but I see a few different problems here.  Every
backend is creating a new dsa area, and then storing the pointer to it
in shared memory instead of attaching from other backends using the
handle, and there are synchronisation problems.  That isn't going to
work.  Here's what I think you might want to try:

1.  In BufferShmemHook, acquire and release AddinShmemInitLock while
initialising "Mahi_Shared_Data" (just like pgss_shmem_startup does),
because any number of backends could be starting up at the same time
and would step on each other's toes here.

2.  When ShmemInitStruct returns, check the value of 'found'.  If it's
false, then this backend is the very first one to attach to this bit
of (traditional) shmem.  So it should create the DSA area and store
the handle in the traditional shmem.  Because we hold
AddinShmemInitLock we know that no one else can be doing that at the
same time.   Before even trying to create the DSA area, you should
probably memset the whole thing to zero so that if you fail later, the
state isn't garbage.  If 'found' is true, then we know it's already
all set up (or zeroed out), so instead of creating the DSA area it
should attach to it using the published handle.

3.  Whether you are the backend that created it or a backend that
attached to it, I think you'll need to store the dsa_area in a global
variable for your UDFs to access.  Note that the dsa_area object will
be different in each backend: there is no point in storing that
address itself in shared memory, as you have it, as you certainly
can't use it in any other backend. In other words, each backend that
attached has its own dsa_area object that it can use to access the
common dynamic shared memory area.

4.  After creating, in this case I think you should call
dsa_pin(area), so that it doesn't go away when there are no backends
attached (ie because there are no backends running) (if I understand
correctly that you want this DSA area to last as long as the whole
cluster).

By the way, in _PG_init() where you have
RequestAddinShmemSpace(100000000) I think you want
RequestAddinShmemSpace(sizeof(shared_data)).

The key point is: only one backend should use LWLockNewTrancheId() and
dsa_create(), and then make the handle available to others; all the
other backends should use dsa_attach().  Then they'll all be attached
to the same dynamic shared memory area and can share data.

-- 
Thomas Munro
http://www.enterprisedb.com



pgsql-hackers by date:

Previous
From: Amit Langote
Date:
Subject: Re: [HACKERS] A bug in mapping attributes in ATExecAttachPartition()
Next
From: Peter Eisentraut
Date:
Subject: Re: [HACKERS] Detection of IPC::Run presence in SSL TAP tests