Thread: MemoryContextSwitchTo() confusion

MemoryContextSwitchTo() confusion

From
Dan Searle
Date:
Hi,

I've written a custom C-language function that takes a SQL select 
statement as it's input parameter, runs the query using the SPI 
interface, iterates over all the results of the select using a cursor 
and collates the data using a tsearch type binary tree, then walks the 
tree to create a flat vector of ordered nodes all in the first call 
(i.e. SRF_IS_FIRSTCALL()). It then contructs tuples, turns them into 
Datums and returns all it's records with subsequent calls.

I've used the example code in the documentation, and used the doxygen 
docs for tablefunc.c as guidelines.

Everything seems to work fine, except on the final call it has no more 
data to return so cleans up all it's internal data structures and 
returns with SRF_RETURN_DONE(funcctx).

I had to fiddle about with switching memory contexts rather a lot to 
make it work this far, but I'm only guessing as to when it's appropriate 
to call MemoryContextSwitchTo(), and to which context to switch to. I 
had a few SEGV's and had to add a few MemoryContextSwitchTo() calls in 
various places, however, can someone please explain the need for 
MemoryContextSwitchTo() and when it's needed, as I'm basically guessing 
and I think it's the reason for the SEGV after the final call to 
SRF_RETURN_DONE() after it's returned all it's tuples.

I have verified that all the code seems to work, and that it is after 
the final call to SRF_RETURN_DONE() that the SEGV happens by writing 
debug strings to a file handle.

I can provide a copy of the sourece code, but I thought it best to ask 
first.

Regards, Dan...


------------------------------------------------------------------------------------
Scanned for viruses, spam and offensive content by CensorNet MailSafe

Professional Web & E-mail Filtering from www.censornet.com


Re: MemoryContextSwitchTo() confusion

From
"Pavan Deolasee"
Date:
On Thu, Mar 20, 2008 at 12:27 AM, Dan Searle <dan@adelix.com> wrote:

>
>  I had to fiddle about with switching memory contexts rather a lot to
>  make it work this far, but I'm only guessing as to when it's appropriate
>  to call MemoryContextSwitchTo(), and to which context to switch to

Here is what I know. Not sure whether it would answer your question though.

A memory context is a memory enclosure with a life associated to it. Whenever
the context is freed, all objects allocated in that context are also
automatically
freed. If there are any references to these objects, they will turn
into dangling
pointers, causing segfaults and/or memory corruption. So you need to be
careful while choosing a memory context to allocate memory from. You
don't want to allocate something in a long-lived context if you don't need
it for that much time because failure to explicitely free the allocation will
result in memory consumption when its not required or even a memory leak.
OTOH you don't want to allocate something in a very short-live context,
if you may require that object outside the scope of that context.

Certain memory contexts are well known. For example, a TopMemoryContext
has life of the session. Any object allocated in this context would remain
valid for the entire session. Of course, failure to free them would result
in memory leaks.

TopTransactionContext, as the name suggests, is valid in the current
top transaction. As soon as the transaction commits/aborts, the context
is freed.

CurrentTransactionContext, which may be same as TopTransactionContext
remains valid for the current transaction or subtransaction.

Apart from that, there are contexts attached to different objects during
execution and their lifespan is usually attached to the lifespan of the object
itself. You may need to choose one of them if you know that what you
are allocating can not or should not outlive that object.


Thanks,
Pavan

-- 
Pavan Deolasee
EnterpriseDB http://www.enterprisedb.com


Re: MemoryContextSwitchTo() confusion

From
NikhilS
Date:
src/backend/utils/mmgr/README contains more information about the same too.

Regards,
Nikhils

On Thu, Mar 20, 2008 at 2:41 PM, Pavan Deolasee <pavan.deolasee@gmail.com> wrote:
On Thu, Mar 20, 2008 at 12:27 AM, Dan Searle <dan@adelix.com> wrote:

>
>  I had to fiddle about with switching memory contexts rather a lot to
>  make it work this far, but I'm only guessing as to when it's appropriate
>  to call MemoryContextSwitchTo(), and to which context to switch to

Here is what I know. Not sure whether it would answer your question though.

A memory context is a memory enclosure with a life associated to it. Whenever
the context is freed, all objects allocated in that context are also
automatically
freed. If there are any references to these objects, they will turn
into dangling
pointers, causing segfaults and/or memory corruption. So you need to be
careful while choosing a memory context to allocate memory from. You
don't want to allocate something in a long-lived context if you don't need
it for that much time because failure to explicitely free the allocation will
result in memory consumption when its not required or even a memory leak.
OTOH you don't want to allocate something in a very short-live context,
if you may require that object outside the scope of that context.

Certain memory contexts are well known. For example, a TopMemoryContext
has life of the session. Any object allocated in this context would remain
valid for the entire session. Of course, failure to free them would result
in memory leaks.

TopTransactionContext, as the name suggests, is valid in the current
top transaction. As soon as the transaction commits/aborts, the context
is freed.

CurrentTransactionContext, which may be same as TopTransactionContext
remains valid for the current transaction or subtransaction.

Apart from that, there are contexts attached to different objects during
execution and their lifespan is usually attached to the lifespan of the object
itself. You may need to choose one of them if you know that what you
are allocating can not or should not outlive that object.


Thanks,
Pavan

--
Pavan Deolasee
EnterpriseDB http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



--
EnterpriseDB http://www.enterprisedb.com

Re: MemoryContextSwitchTo() confusion

From
"korry"
Date:
> Everything seems to work fine, except on the final call it has no more 
> data to return so cleans up all it's internal data structures and 
> returns with SRF_RETURN_DONE(funcctx).
If you are doing your development work on a Linux host, you may find it 
useful to run the postmaster through valgrind 
(http://en.wikipedia.org/wiki/Valgrind).

valgrind can spot many (but not all) memory-related problems and makes 
it easier to track them to their source.  Be aware that valgrind's 
memory leak features may be pretty useless with PostgreSQL.

To run the server (and all backend processes) under valgrind:
   $ valgrind --trace-children=yes --log-file=/tmp/pg.vg pg_ctl start

After that, you'll see one /tmp/pg.vg.<processID> file for each process 
spawned by pg_ctl/postmaster.  Use "SELECT * FROM pg_backend_pid()" to 
find the processID of the backend where you are testing your extensions 
and then look through the valgrind output file for that process.
            -- Korry

-- 
 Korry Douglas  <korryd@enterprisedb.com> EnterpriseDB    http://www.enterprisedb.com