SRF's + SPI

From: Eric B(dot)Ridge <ebr(at)tcdi(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: SRF's + SPI
Date: 2005-04-01 18:25:21
Message-ID: da7c7eb07f7d2f295e53b936ecf07983@tcdi.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

With pg v7.4.7 I've written an SRF that uses SPI to return the results
of a query. It's one of those functions that works perfectly for me in
development but randomly crashes in production. Thus far I've been
unable to reproduce the crash. The problem is surely in my code. And
before I dig into debugging the hard stuff I would love a sanity check
to verify that I'm using SPI_connect()/SPI_finish() correctly within
the context of the SRF.

The backtrace from a core dump:
(gdb) bt
#0 0x0820ee29 in pfree ()
#1 0x08204a18 in end_MultiFuncCall ()
#2 0x4cee0f99 in my_src (fcinfo=0xbfffccd0) at foo.c:93
#3 0x0811058b in ExecMakeTableFunctionResult ()
#4 0x08750c78 in ?? ()
#5 0x00004000 in ?? ()
#6 0xbfffccac in ?? ()
#7 0xbfffcd88 in ?? ()

And the code at foo.c:93
SRF_RETURN_DONE(funcctx);

I'm wondering if I'm using SPI incorrectly. In the past I've had
issues with incorrectly using SPI (esp with recursion), and I'm not
entirely sure how it should work with SRF's. Like I said, everything
usually works without problems, but from time to time it crashes.
Below is the basic outline of my code.

Any input will be greatly appreciated.

thanks!

eric

------------------------------
Datum my_srf (PG_FUNCTION_ARGS) {
FuncCallContext *funcctx;

if (SRF_IS_FIRSTCALL()) {
MemoryContext oldcontext;
char *query;

if(PG_ARGISNULL(0))
SRF_RETURN_DONE(NULL); /* nothing to expand when arg[0] is null */

funcctx = SRF_FIRSTCALL_INIT();

oldcontext =
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

query = < function call to build a query string >;

SPI_connect();
if (SPI_exec(query, 0) != SPI_OK_SELECT)
elog(ERROR, "unable to execute fulltext query");

funcctx->slot = TupleDescGetSlot(SPI_tuptable->tupdesc);
funcctx->attinmeta = TupleDescGetAttInMetadata(SPI_tuptable->tupdesc);
funcctx->user_fctx = SPI_tuptable;
funcctx->call_cntr = 0;
funcctx->max_calls = SPI_processed;

MemoryContextSwitchTo(oldcontext);
}

funcctx = SRF_PERCALL_SETUP();

if (funcctx->call_cntr < funcctx->max_calls) {
SPITupleTable *tuptable = (SPITupleTable *) funcctx->user_fctx;
HeapTuple tuple;
Datum result;

tuple = tuptable->vals[funcctx->call_cntr];
result = TupleGetDatum(funcctx->slot, tuple);

SRF_RETURN_NEXT(funcctx, result);
} else {
SPI_finish();
line_93:
SRF_RETURN_DONE(funcctx); /** XXX: CRASH HERE **/
}

PG_RETURN_NULL();
}

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Mark Woodward 2005-04-01 18:50:35 Re: ARC patent
Previous Message Andrew Dunstan 2005-04-01 17:11:39 Re: ARC patent