Re: C set return function differences on 8.0?]] - Mailing list pgsql-interfaces

From Tim Jackson
Subject Re: C set return function differences on 8.0?]]
Date
Msg-id 42D2E683.5080302@ints.com
Whole thread Raw
Responses Re: C set return function differences on 8.0?]]
List 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 =
(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);   }
 
}






pgsql-interfaces by date:

Previous
From: Dirk Jagdmann
Date:
Subject: ecpg and VARCHAR
Next
From: Tim Jackson
Date:
Subject: Re: C set return function differences on 8.0?