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: