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 =
(unsignedchar *)buffer1; char buffer2[256]; unsigned char * bufptr2 = (unsigned char *)buffer2; char buffer3[256];
unsignedchar * 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;
intnum_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-6Wide","Y"); strcat (record, buffer1); sprintf (buffer1, "%s|%s|%s|%s|",
"10","1010.01","10-6Wide","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); }
}