Thread: fmgr_oldstyle in extensions
Hi all, I’m trying to implement an spgist index in the PostGIS extension, which seems like it should work, but is thus far not workingfor what appear (to me) to be issues in the way spgist expects to pass pointers to user-defined functions. Right before anything happens, spgist calls a ‘config’ routine in the user code. This is the code from the example implementation(which is internal to pgsql, not a run-time add-on like postgis) Datum spg_quad_config(PG_FUNCTION_ARGS) { /* spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0); */ spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1); cfg->prefixType = POINTOID; cfg->labelType = VOIDOID; /* we don't need node labels */ cfg->canReturnData = true; cfg->longValuesOK = false; PG_RETURN_VOID(); } It is called from the spgist core in the spgGetCache() function, via FunctionCall2Coll(procinfo, index->rd_indcollation[0], PointerGetDatum(&in), PointerGetDatum(&cache->config)); The part the user function cares about is the pointer to cache->config. In the core code, the call stack to the user function goes like this: postgres`spg_quad_config(fcinfo=0x00007fff5f0faf90) + 18 at spgquadtreeproc.c:29 postgres`FunctionCall2Coll(flinfo=0x00007ff59a804cc8, collation=0, arg1=140734788252568, arg2=140692835814944) + 150 at fmgr.c:1327 postgres`spgGetCache(index=0x000000010254be68) + 220 at spgutils.c:71 So, spgGetCache to FunctionCall2Coll to spg_quad_config. In my user-defined version of the same thing (I just copied the C code and wrote a CREATE OPERATOR CLASS for it) the callstack is this postgis-2.2.so`gserialized_spgist_quadtree_2d_config(fcinfo=0x00007fff5f0fb398) + 30 at gserialized_spgist_2d.c:60 postgres`fmgr_oldstyle(fcinfo=0x00007fff5f0faf90) + 424 at fmgr.c:678 postgres`FunctionCall2Coll(flinfo=0x00007ff59a039cc8, collation=0, arg1=140734788252568, arg2=140692827643424) + 150 at fmgr.c:1327 postgres`spgGetCache(index=0x000000010254be68) + 220 at spgutils.c:71 So, spgGetCache to FunctionCall2Coll to fmgr_oldstyle to gserialized_spgist_quadtree_2d_config! On the way through fmgr_oldstyle things go very much awry and the gserialized_spgist_quadtree_2d_config doesn’t get calledwith a pointer to an fcinfo, but with a pointer to the block of memory occupied by the first argument, and from therethings naturally stop working. So, I’m wondering what I could have done that is causing my calls to route through fmgr_oldstyle instead of the usual path? P. -- Paul Ramsey http://cleverelephant.ca http://postgis.net
Hi Paul, On 2014-09-23 09:55:32 -0700, Paul Ramsey wrote: > I’m trying to implement an spgist index in the PostGIS extension, which seems like it should work, but is thus far notworking for what appear (to me) to be issues in the way spgist expects to pass pointers to user-defined functions. > > Right before anything happens, spgist calls a ‘config’ routine in the user code. This is the code from the example implementation(which is internal to pgsql, not a run-time add-on like postgis) > > Datum > spg_quad_config(PG_FUNCTION_ARGS) > { > /* spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0); */ > spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1); > > cfg->prefixType = POINTOID; > cfg->labelType = VOIDOID; /* we don't need node labels */ > cfg->canReturnData = true; > cfg->longValuesOK = false; > PG_RETURN_VOID(); > } > > It is called from the spgist core in the spgGetCache() function, via > > FunctionCall2Coll(procinfo, > index->rd_indcollation[0], > PointerGetDatum(&in), > PointerGetDatum(&cache->config)); > > The part the user function cares about is the pointer to cache->config. > > In the core code, the call stack to the user function goes like this: > > postgres`spg_quad_config(fcinfo=0x00007fff5f0faf90) + 18 at spgquadtreeproc.c:29 > postgres`FunctionCall2Coll(flinfo=0x00007ff59a804cc8, collation=0, arg1=140734788252568, arg2=140692835814944) + 150 atfmgr.c:1327 > postgres`spgGetCache(index=0x000000010254be68) + 220 at spgutils.c:71 > > So, spgGetCache to FunctionCall2Coll to spg_quad_config. > > In my user-defined version of the same thing (I just copied the C code and wrote a CREATE OPERATOR CLASS for it) the callstack is this > > postgis-2.2.so`gserialized_spgist_quadtree_2d_config(fcinfo=0x00007fff5f0fb398) + 30 at gserialized_spgist_2d.c:60 > postgres`fmgr_oldstyle(fcinfo=0x00007fff5f0faf90) + 424 at fmgr.c:678 > postgres`FunctionCall2Coll(flinfo=0x00007ff59a039cc8, collation=0, arg1=140734788252568, arg2=140692827643424) + 150 atfmgr.c:1327 > postgres`spgGetCache(index=0x000000010254be68) + 220 at spgutils.c:71 > > So, spgGetCache to FunctionCall2Coll to fmgr_oldstyle to > gserialized_spgist_quadtree_2d_config! > > On the way through fmgr_oldstyle things go very much awry and the gserialized_spgist_quadtree_2d_config doesn’t get calledwith a pointer to an fcinfo, but with a pointer to the block of memory occupied by the first argument, and from therethings naturally stop working. > > So, I’m wondering what I could have done that is causing my calls to route through fmgr_oldstyle instead of the usual path? You forgot to add a PG_FUNCTION_INFO_V1(yourfunc); for the function. I really, really think we should get rid of v0 functions. I've seen errors like this far too many, and they really don't buy us much. Greetings, Andres Freund -- Andres Freund http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
Oh vey, I knew after spending a half-day walking through the debugger it would turn out to be a trivial mistake on my part. This is always how it is when the Magic Fails to Work :) Thanks so much for the help! (and now I know a lot more about the function manager (well, the old one)).
P
Paul Ramsey
http://cleverelephant.ca
http://postgis.net
On September 23, 2014 at 10:02:33 AM, Andres Freund (andres@2ndquadrant.com) wrote:
You forgot to add a PG_FUNCTION_INFO_V1(yourfunc); for the function.