Thread: MemoryContextSwitchTo() confusion
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
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
src/backend/utils/mmgr/README contains more information about the same too.
Regards,
Nikhils
--
EnterpriseDB http://www.enterprisedb.com
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:Here is what I know. Not sure whether it would answer your question though.
>
> 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
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
> 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