pg.ddx.io pgsql-interfaces@postgresql.org mailing list archive
help / color / mirror / Atom feedC set return function differences on 8.0?
7+ messages / 3 participants
[nested] [flat]
* C set return function differences on 8.0?
@ 2005-07-08 00:58 Tim Jackson <tim.jackson@ints.com>
2005-07-08 15:23 ` Re: C set return function differences on 8.0? Michael Fuhr <mike@fuhr.org>
0 siblings, 1 reply; 7+ messages in thread
From: Tim Jackson @ 2005-07-08 00:58 UTC (permalink / raw)
To: pgsql-interfaces
I have a C .so set return function which is called to create a views,
pulling data from an older non SQL flat file data structure
CREATE OR REPLACE VIEW view_name AS
SELECT call_d.col_0, call_d.col_1, call_d.col_2, call_d.col_3"
FROM call_d('select * from aname '::text, 'aname'::text) AS (col_0
bigint, col_2 numeric, col_2 text, col_3 text);
The call_d function calls the C .so passing in the SQL and the target
and returns a record set conforming to the request, the column names and
data types are supplied for each target/view
This worked compiled under postgresql 7.4 for all the target files and
various data types that I have.
I re-compiled the .so using 8.0 server development source and rebuilt
the views on 8.0 and now only some views will pull up data. These are
views using the same data that worked under 7.4 and now just abort.
Some of the views do select.
Could the problem be related to a difference in the way 8.0 is handling
data types?
When I define a column as numeric with out precision or scale it should
handle any numeric value, however in a data set that has a numeric field
with mostly XX.XX data one record had a XX.XXX value and once I removed
that record from the set the view selected ok.
This doesn't make sense to me.
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: C set return function differences on 8.0?
2005-07-08 00:58 C set return function differences on 8.0? Tim Jackson <tim.jackson@ints.com>
@ 2005-07-08 15:23 ` Michael Fuhr <mike@fuhr.org>
2005-07-09 01:58 ` Re: C set return function differences on 8.0? Michael Fuhr <mike@fuhr.org>
0 siblings, 1 reply; 7+ messages in thread
From: Michael Fuhr @ 2005-07-08 15:23 UTC (permalink / raw)
To: Tim Jackson <tim.jackson@ints.com>; +Cc: pgsql-interfaces
On Thu, Jul 07, 2005 at 05:58:28PM -0700, Tim Jackson wrote:
>
> I re-compiled the .so using 8.0 server development source and rebuilt
> the views on 8.0 and now only some views will pull up data. These are
> views using the same data that worked under 7.4 and now just abort.
What do you mean by "abort" -- does the backend crash? If so, and
if you get a core dump, then it might be useful to see a stack trace.
Could you post a simple, self-contained test case that works in 7.4
and fails in 8.0? That is, all SQL, C code, and data that somebody
could use to reproduce the problem from an empty database. Please
do distill the example so it's as simple as possible -- that way
the analysis won't be distracted by irrelevant factors.
Exactly which versions of 7.4 and 8.0 are you running, and on what
platform?
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: C set return function differences on 8.0?
2005-07-08 00:58 C set return function differences on 8.0? Tim Jackson <tim.jackson@ints.com>
2005-07-08 15:23 ` Re: C set return function differences on 8.0? Michael Fuhr <mike@fuhr.org>
@ 2005-07-09 01:58 ` Michael Fuhr <mike@fuhr.org>
2005-07-09 02:13 ` Re: C set return function differences on 8.0? Tom Lane <tgl@sss.pgh.pa.us>
2005-07-11 23:09 ` Re: C set return function differences on 8.0? Tim Jackson <tim.jackson@ints.com>
0 siblings, 2 replies; 7+ messages in thread
From: Michael Fuhr @ 2005-07-09 01:58 UTC (permalink / raw)
To: Tim Jackson <tim.jackson@ints.com>; +Cc: pgsql-interfaces
[Please copy the mailing list on replies so others can contribute
to and learn from the discussion.]
On Fri, Jul 08, 2005 at 05:12:58PM -0700, Tim Jackson wrote:
> Michael Fuhr wrote:
> > What do you mean by "abort" -- does the backend crash? If so, and
> > if you get a core dump, then it might be useful to see a stack trace.
> >
> The backend crashes, in pgadmin attempting to display the view simple
> says aborting. There is no core dump, and the log only seems to reflect
> the standard
> WARNING: terminating connection because of crash of another server process
Where did you look for a core dump? If one was made then it'll
probably be somewhere under $PGDATA (e.g., $PGDATA/base/XXX/core)
unless your system is configured to put core dumps elsewhere.
If there isn't a core dump then you could add some debugging ereport()
calls to your code so you can find out where the crash is happening.
Another possibility might be to attach a debugger to the backend.
> >Could you post a simple, self-contained test case that works in 7.4
> >and fails in 8.0? That is, all SQL, C code, and data that somebody
> >
> The problem I have is we are using a licensed library to accesss the
> target database. We have c code which parses SQLSRF and makes a call to
> these 3rd party lib functions which returns strings of data.
So your C function calls these library functions, which query some
other data source and return strings back to you, right? How are
these strings returned -- as char * values? Can you at least post
your code?
> Today we tried to just hard code some data strings and pass that into
> SRF part of the code. We put in values that we expected to cause the
> problem and it did not cause the problem. So we are stuck with how to
> proceed.
Let's see if attaching a debugger to the backend or adding some
ereport() calls can at least tell us where the crash is happening.
Then maybe we can figure out why.
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: C set return function differences on 8.0?
2005-07-08 00:58 C set return function differences on 8.0? Tim Jackson <tim.jackson@ints.com>
2005-07-08 15:23 ` Re: C set return function differences on 8.0? Michael Fuhr <mike@fuhr.org>
2005-07-09 01:58 ` Re: C set return function differences on 8.0? Michael Fuhr <mike@fuhr.org>
@ 2005-07-09 02:13 ` Tom Lane <tgl@sss.pgh.pa.us>
1 sibling, 0 replies; 7+ messages in thread
From: Tom Lane @ 2005-07-09 02:13 UTC (permalink / raw)
To: Michael Fuhr <mike@fuhr.org>; +Cc: Tim Jackson <tim.jackson@ints.com>; pgsql-interfaces
Michael Fuhr <mike@fuhr.org> writes:
> On Fri, Jul 08, 2005 at 05:12:58PM -0700, Tim Jackson wrote:
>> The backend crashes, in pgadmin attempting to display the view simple
>> says aborting. There is no core dump, and the log only seems to reflect
>> the standard
>> WARNING: terminating connection because of crash of another server process
> Where did you look for a core dump?
"There is no core dump" is not an acceptable answer: if there isn't one,
the first item on your agenda must be to get one (or else run the
problem case under gdb so you don't need a dump to get a stack trace).
Usually if there's no dump it's because the default configuration on
your system is "ulimit -c 0" to suppress core dumps from daemons.
Put "ulimit -c unlimited" (or local equivalent) into your postmaster
start script and restart the postmaster.
On the whole though I'd recommend learning how to attach gdb to a live
backend, since then not only can you get a stack trace from the point of
the fault, but you can then work backwards by setting breakpoints ahead
of the crash and stepping through the code to see where it goes wrong.
regards, tom lane
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: C set return function differences on 8.0?
2005-07-08 00:58 C set return function differences on 8.0? Tim Jackson <tim.jackson@ints.com>
2005-07-08 15:23 ` Re: C set return function differences on 8.0? Michael Fuhr <mike@fuhr.org>
2005-07-09 01:58 ` Re: C set return function differences on 8.0? Michael Fuhr <mike@fuhr.org>
@ 2005-07-11 23:09 ` Tim Jackson <tim.jackson@ints.com>
1 sibling, 0 replies; 7+ messages in thread
From: Tim Jackson @ 2005-07-11 23:09 UTC (permalink / raw)
To: Michael Fuhr <mike@fuhr.org>; +Cc: pgsql-interfaces
Michael Fuhr wrote:
>
>Let's see if attaching a debugger to the backend or adding some
>ereport() calls can at least tell us where the crash is happening.
>Then maybe we can figure out why.
>
>
I was able to set gdb to the pid of psql session and saw that selects
on the "bad" views segfaulted on pfree()
The documentation for SRF had a comment that said pfree() was not really
necessary so I commented that code out and now I can select all the
views. :)
Perhaps you can advise me on why pfree() would segfault on 8.0 in but
not 7.4
Anyway the .so generated views are working now as they were on 7.4.
Thanks for your help. Tim
Not sure what all this means but the following lines were gleaned from
the core dump
cannot allocate memory for thread-local data: ABORT
result == _rtld_local._dl_tls_max_dtv_idx + 1
result <= _rtld_local._dl_tls_max_dtv_idx + 1
@cnt < _rtld_local._dl_tls_dtv_slotinfo_list->len
_rtld_local._dl_tls_dtv_slotinfo_list->next == ((void *)0)
_rtld_local._dl_tls_dtv_slotinfo_list != ((void *)0)
_rtld_local._dl_tls_max_dtv_idx == 0
_rtld_local._dl_tls_dtv_slotinfo_list == ((void *)0)
(size_t) map->l_tls_offset >= map->l_tls_blocksize
map->l_tls_blocksize >= map->l_tls_initimage_size
../sysdeps/unix/sysv/linux/dl-origin.c
FATAL: cannot determine library version
../sysdeps/generic/dl-sysdep.c
Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!
Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.
And Here is what gdb says about the core
Core was generated by `postgres: postgres lubesoft_tj [local]
SELECT '.
Program terminated with signal 11, Segmentation fault.
#0 0x08222a86 in ?? ()
(no debugging symbols found)...Using host libthread_db library
"/lib/tls/libthread_db.so.1".
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: C set return function differences on 8.0?]]
@ 2005-07-11 21:37 Tim Jackson <tim.jackson@ints.com>
2005-07-12 14:31 ` Re: C set return function differences on 8.0?]] Tom Lane <tgl@sss.pgh.pa.us>
0 siblings, 1 reply; 7+ messages in thread
From: Tim Jackson @ 2005-07-11 21:37 UTC (permalink / raw)
To: pgsql-interfaces
Michael Fuhr wrote:
>Where did you look for a core dump? If one was made then it'll
>probably be somewhere under $PGDATA (e.g., $PGDATA/base/XXX/core)
>unless your system is configured to put core dumps elsewhere.
>
>
>
I was able to get the core dump by adding 'ulimit -c unlimited' to the
start script
(thanks Tom)
It is huge (14 megs)
One interesting thing happened once the core dump is created.
Now if I re connect to the data base and rerun the select on the view
after it has crashed once it will select the view.
>If there isn't a core dump then you could add some debugging ereport()
>calls to your code so you can find out where the crash is happening.
>Another possibility might be to attach a debugger to the backend.
>
>
>
If you can tell me how to do that. I tried attaching gdb to the running
servers pid and it seems to lock up the server.
>So your C function calls these library functions, which query some
>other data source and return strings back to you, right? How are
>these strings returned -- as char * values? Can you at least post
>your code?
>
>
>
The full so code is 4000 lines and caused the news group to reject the mail
, but here is the basic format with the piece that builds the record replaced
by hardcoded values.
/*******************************/
//
// Program: call_good.c
//
// Listing Date: 07/08/2005
//
/*******************************/
#include "server/postgres.h"
#include "server/fmgr.h"
#include "server/funcapi.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define OK 0
#define ERROR1 (-1)
#define YES 1
#define NO 0
#define DATA1 2
#define MAYBE 2
char record[1024 * 1024];
char buffer[256];
unsigned char * bufptr = (unsigned char *)buffer;
char buffer1[256];
unsigned char * bufptr1 = (unsigned char *)buffer1;
char buffer2[256];
unsigned char * bufptr2 = (unsigned char *)buffer2;
char buffer3[256];
unsigned char * bufptr3 = (unsigned char *)buffer3;
int count, count1;
long CurrentSize;
char request[8192];
char response[512];
char typedefin[1024];
int max_fields;
int field_lengths[256];
char field_types[256][16];
char *record_add;
char parsed[256];
char *select_add;
char *from_add;
char *where_add;
char *end_add;
char select1[8192];
char from[512];
char where[512];
FILE *stream;
FILE *stream1;
char filein[128];
char fileout[128];
char filename_out[128];
int num_targets_work;
int num_targets_index;
int chunk_amount = 5;
int chunk_counter;
int fileOpen;
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tupdesc;
TupleTableSlot *slot;
AttInMetadata *attinmeta;
/***********************************/
// select_more_data
/***********************************/
int tselect_more_data (void)
{
int recordFound;
memset (record, 0, sizeof(record));
sprintf (buffer1, "%s|%s|%s|%s|", "6","6666.01","6-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "7","7777.01","7-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "8","888888.0001","8-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "9","9999.01","9-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "10","1010.01","10-6 Wide","Y");
strcat (record, buffer1);
count = 5;
if (count)
recordFound = DATA1;
return (recordFound);
}
/***********************************/
// select_data
/***********************************/
int tselect_data (void)
{
int recordFound;
memset (record, 0, sizeof(record));
sprintf (buffer1, "%s|%s|%s|%s|", "1","1111.01","1-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "2","2222.01","2-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "3","3333.01","3-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "4"," 4444.01","4-6 Wide","Y");
strcat (record, buffer1);
sprintf (buffer1, "%s|%s|%s|%s|", "5","5555.01","5-8 Wide","Y");
strcat (record, buffer1);
count = 5;
if (count)
recordFound = DATA1;
return (recordFound);
}
/***********************************/
// select_field_lengths
/***********************************/
int tselect_field_lengths (void)
{
int recordFound;
int len;
CurrentSize = 10;
len = 3;
field_lengths[0] = len * 2 + 1;
strcpy (field_types[0], "numeric");
len = 4;
field_lengths[1] = len * 2 + 1;
strcpy (field_types[1], "numeric");
len = 30;
field_lengths[2] = len;
strcpy (field_types[2], "string");
len = 1;
field_lengths[3] = len;
strcpy (field_types[3], "string");
max_fields = 4;
recordFound = DATA1;
return (recordFound);
}
/***********************************/
// parse_record
/***********************************/
void tparse_record (void)
{
char *ptr;
char *ptr1;
ptr = record_add;
ptr1 = strchr (ptr, '|');
if (ptr1)
{
*ptr1 = 0;
strcpy (parsed,ptr);
}
record_add = ++ptr1;
}
/***********************************/
// parse_sql
/***********************************/
int tparse_sql (char * request)
{
int func;
select_add =
from_add =
where_add =
end_add = 0L;
memset ( select1, 0, sizeof(select1));
memset ( from, 0, sizeof(from));
memset ( where, 0, sizeof(where));
select_add = strstr(request, "SELECT ");
if (select_add == 0)
select_add = strstr(request, "select ");
if (select_add != 0)
{
from_add = strstr(request, "FROM ");
if (from_add == 0)
from_add = strstr(request, "from ");
}
where_add = strstr(request, "WHERE ");
if (where_add == 0)
where_add = strstr(request, "where ");
if (select_add != 0)
{
end_add = select_add+strlen(request);
func = 40;
}
else
{
func = 999;
return func;
}
if (select_add != 0)
{
memcpy ( select1, select_add, from_add-select_add);
if (where_add == 0)
{
memcpy ( from, from_add, end_add-from_add);
}
else if (where_add)
{
memcpy ( from, from_add, where_add-from_add);
memcpy ( where, where_add, end_add-where_add);
}
}
return func;
}
/************************************/
PG_FUNCTION_INFO_V1 (call_good);
Datum
call_good (PG_FUNCTION_ARGS)
{
int i, func, retval;
// stuff done only on the first call of the function
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
text *t = PG_GETARG_TEXT_P(0);
text *t1 = PG_GETARG_TEXT_P(1);
memset (request, 0, sizeof(request));
strncpy (request, t->vl_dat, t->vl_len- VARHDRSZ);
memset (typedefin, 0, sizeof(typedefin));
strncpy (typedefin, t1->vl_dat, t1->vl_len- VARHDRSZ);
// create a function context for cross-call persistence
funcctx = SRF_FIRSTCALL_INIT();
// switch to memory context appropriate for multiple function calls
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
// Build a tuple description for a incoming type tuple
tupdesc = RelationNameGetTupleDesc(typedefin);
// allocate a slot for a tulpe with this tupdesc
slot = TupleDescGetSlot(tupdesc);
// assign slot to function context
funcctx->slot = slot;
// Generate attribute metadata needed later to produce
// tupples from raw C strings
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;
MemoryContextSwitchTo(oldcontext);
strcpy (fileout, "pfxG");
sprintf (filename_out, "/tmp/%s.rsp", fileout); // rf
if ((stream1 = fopen (filename_out, "wb")) == NULL)
{
return 1;
}
if ((stream = fopen ("/tmp/call_good.log", "a+")) == NULL)
{
return 1;
}
fprintf (stream1,"Call_Good\n");
fprintf (stream1,"request>%s<\n",request);
fprintf (stream1,"file: %s\n",typedefin);
func = tparse_sql (request);
record_add = 0;
tselect_field_lengths();
fprintf (stream,"NumRecs = %ld NumFields = %d\n",
CurrentSize, max_fields);
for (i=0; i < max_fields; i++)
{
fprintf (stream1,"Field: %3d Type: %-8s Length: %d\n",
i,field_types[i],field_lengths[i]);
}
switch (func)
{
case 40:
if (select_add)
{
fprintf (stream1, "select: %s\n",select1);
fprintf (stream1, "from: %s\n",from);
if (where_add)
{
fprintf (stream1, "where: %s\n",where);
}
}
funcctx->max_calls = CurrentSize;
// Go get first chunk of records from file
retval = tselect_data();
if (retval != DATA1)
{
strcpy (record, "Not Found\n");
fwrite (record, strlen(record), 1, stream1);
}
break;
case 999:
strcpy (record, "Invalid Statement");
fwrite (record, strlen(record), 1, stream1);
break;
default:
strcpy (record, "Invalid");
fwrite (record, strlen(record), 1, stream1);
retval = NO;
break;
}
fprintf (stream,"Count = %ld Data = %.50s\n",CurrentSize,record);
fprintf (stream,"File: %s Type: %s\n",filein,typedefin);
record_add = record;
chunk_counter = chunk_amount;
fflush (stream);
}
// stuff done on every call of the function
funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
slot = funcctx->slot;
attinmeta = funcctx->attinmeta;
if (call_cntr < max_calls)
{
char **values;
HeapTuple tuple;
Datum result;
if (call_cntr == chunk_counter)
{
// Go get next chunk of records from file
retval = tselect_more_data();
record_add = record;
chunk_counter += chunk_amount;
}
// Prepare a values array for storage in our slot.
// This should be an array of C strings which will
// be processed later by the appropriate "in" functions.
values = (char **) palloc(max_fields * sizeof(char *));
for (i=0; i < max_fields; i++)
{
values[i] = (char *) palloc(field_lengths[i] * sizeof(char));
}
for (i=0; i < max_fields; i++)
{
tparse_record();
if (strlen(parsed) == 0 && strcmp(field_types[i],"date") == 0)
{
strcpy (values[i], "01/01/1980");
}
else
{
strcpy (values[i], parsed);
}
}
// build a tuple
tuple = BuildTupleFromCStrings(attinmeta, values);
// make the tuple into a datum
result = TupleGetDatum(slot,tuple);
// result = HeapTupleGetDatum(tuple);
// Clean up (this is not actually necessary)
for (i=0; i < max_fields; i++)
{
pfree(values[i]);
}
pfree(values);
fflush (stream);
SRF_RETURN_NEXT(funcctx, result);
}
else // do when there is no more left
{
if (fileOpen)
{
fprintf (stream, "EOD Set5\n");
fileOpen = 0;
}
fprintf (stream1,"DONE: call_cntr= %d max_calls= %d\n",
call_cntr,max_calls);
fclose (stream1);
fclose (stream);
SRF_RETURN_DONE(funcctx);
}
}
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: C set return function differences on 8.0?]]
2005-07-11 21:37 Re: C set return function differences on 8.0?]] Tim Jackson <tim.jackson@ints.com>
@ 2005-07-12 14:31 ` Tom Lane <tgl@sss.pgh.pa.us>
0 siblings, 0 replies; 7+ messages in thread
From: Tom Lane @ 2005-07-12 14:31 UTC (permalink / raw)
To: Tim Jackson <tim.jackson@ints.com>; +Cc: pgsql-interfaces
Tim Jackson <tim.jackson@ints.com> writes:
> The full so code is 4000 lines and caused the news group to reject the mail
> , but here is the basic format with the piece that builds the record replaced
> by hardcoded values.
With all those unchecked strcat's and strcpy's going on, it seems like
an excellent bet that you're overrunning one or another buffer and
clobbering memory that doesn't belong to you. Compiling the backend
with --enable-cassert might help in localizing the problem.
regards, tom lane
^ permalink raw reply [nested|flat] 7+ messages in thread
end of thread, other threads:[~2005-07-12 14:31 UTC | newest]
Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2005-07-08 00:58 C set return function differences on 8.0? Tim Jackson <tim.jackson@ints.com>
2005-07-08 15:23 ` Michael Fuhr <mike@fuhr.org>
2005-07-09 01:58 ` Michael Fuhr <mike@fuhr.org>
2005-07-09 02:13 ` Tom Lane <tgl@sss.pgh.pa.us>
2005-07-11 23:09 ` Tim Jackson <tim.jackson@ints.com>
2005-07-11 21:37 Re: C set return function differences on 8.0?]] Tim Jackson <tim.jackson@ints.com>
2005-07-12 14:31 ` Re: C set return function differences on 8.0?]] Tom Lane <tgl@sss.pgh.pa.us>
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox