Re: [GENERAL] User-defined-type in C crashing PostgreSQL server: What am I doing wrong?

2006-11-18 Thread Martijn van Oosterhout
On Sat, Nov 18, 2006 at 01:07:15PM -0800, J. Greg Davidson wrote:
> Hello, 
> 
> My user-defined types are crashing the PostgreSQL server and I don't
> understand why.  I've been trying to figure it out on my own for overr
> a week.  I've cooked what I'm doing down to the essentials and I'm
> asking for help.  Help: What am I doing wrong?

This may be a long shot but:

> CREATE TYPE pair (
>   INTERNALLENGTH = 4, -- 32-bits
>   INPUT = pair_in,
>   OUTPUT = pair_out
> );

You're not specifying PASSEDBYVALUE, so I think postgres is assuming
you're returning a *pointer* to 4 bytes, so it's dying trying to copy
it.

Hope this helps,
-- 
Martijn van Oosterhout  http://svana.org/kleptog/
> From each according to his ability. To each according to his ability to 
> litigate.


signature.asc
Description: Digital signature


[GENERAL] User-defined-type in C crashing PostgreSQL server: What am I doing wrong?

2006-11-18 Thread J. Greg Davidson
Hello, 

My user-defined types are crashing the PostgreSQL server and I don't
understand why.  I've been trying to figure it out on my own for overr
a week.  I've cooked what I'm doing down to the essentials and I'm
asking for help.  Help: What am I doing wrong?

* Sections of this message:
** Overview with psql session
** SQL code
** C Code
** gdb backtraces
***  gdb backtrace after SELECT ARRAY[ pair_tag_id(3, 4) ];
***  gdb backtrace after SELECT x from pair_tag_id(3, 4) x;
***  gdb backtrace after SELECT ROW( pair_tag_id(3, 4) );
** Thanks for your help!

** Overview wiith psql session

Tested with: PostgreSQL-8.1.4 and  PostgreSQL-8.2beta3,
installed from source with
./configure ... --enable-debug --enable-cassert
Platform: SuSE Linux 10.0 on i686 Dell Notebook Computer

I have a simple one-word datatype called a "pair", which consists of a
1-byte "tag" and a 3-byte "id".  

-- At first, it seems to work:

pairs=# select pair_tag_id(3, 4);
   pair_tag_id   
-
 
(1 row)

pairs=# select tag_pair(pair_tag_id(3, 4));
 tag_pair 
--
3
(1 row)

pairs=# select id_pair(pair_tag_id(3, 4));
 id_pair 
-
   4
(1 row)

-- But all three of these crash the server with Signal 11:

SELECT ARRAY[ pair_tag_id(3, 4) ];

SELECT x from pair_tag_id(3, 4) x;

SELECT ROW( pair_tag_id(3, 4) );

-- Note:Nothing special about 3 and 4, all values I've tried behave
--  the same!

** SQL code

-- CREATE TYPE pair; -- PostgreSQL 8.2

CREATE OR REPLACE
FUNCTION pair_in(cstring) RETURNS pair
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE OR REPLACE
FUNCTION pair_out(pair) RETURNS cstring
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE TYPE pair (
  INTERNALLENGTH = 4,   -- 32-bits
  INPUT = pair_in,
  OUTPUT = pair_out
);

CREATE OR REPLACE
FUNCTION tag_pair(pair) RETURNS integer
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE OR REPLACE
FUNCTION id_pair(pair) RETURNS integer
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE OR REPLACE
FUNCTION pair_tag_id(integer, integer) RETURNS pair
AS 'pair.so' LANGUAGE 'c' STRICT;

** C Code

$ cc -fpic -I/Ubuntu/usr/local/pgsql-8.1.4/include/server -Wall   -c -o
pair.o pair.c
$ cc -shared -o pair.so pair.o
$ cat pair.c

#include 
#include 
#include 
#include/* general Postgres declarations */
#include/* for argument/result macros */

#define PAIR_TAG_WIDTH 8
#define PAIR_MAX_TAG ( (1U << PAIR_TAG_WIDTH) - 1)
#define PAIR_MAX_ID ( (int) (INT_MAX >> PAIR_TAG_WIDTH) )
#define PAIR_MIN_ID ( -PAIR_MAX_ID )

typedef long pairs; // a tag plus an ID
typedef unsigned tags;
#define F_TAG "tag: %u "// Format string for tags
typedef long ids;
#define F_ID "id: %ld " // Format string for ids

typedef char *StrPtr;   // '\0' terminated modifiable string
typedef const char *Str;// '\0' terminated constant string

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

inline pairs TagPairId (tags tag, ids id) {
  return (id << PAIR_TAG_WIDTH) | tag;
}
inline tags TagPair(pairs v) {
  return v & ~(~0U <<  PAIR_TAG_WIDTH);
}
inline ids IdPair(pairs v) {
  return v >> PAIR_TAG_WIDTH;
}

#define FUNCTION_DEFINE(f)  \
PG_FUNCTION_INFO_V1(f); \
Datum (f)(PG_FUNCTION_ARGS)

FUNCTION_DEFINE(pair_tag_id) {  // (tags, ids) -> pair
  tags tag = PG_GETARG_INT32(0);
  ids  id =  PG_GETARG_INT32(1);
  PG_RETURN_INT32( TagPairId( tag,  id) );
}

FUNCTION_DEFINE(tag_pair) { // (pair) ->  tags
  PG_RETURN_INT32( TagPair( PG_GETARG_INT32(0) ) );
}

FUNCTION_DEFINE(id_pair) {  // (pair) -> ids
  PG_RETURN_INT32( IdPair( PG_GETARG_INT32(0) ) );
}

inline StrPtr NewStr( Str old ) {
  return strcpy( palloc(strlen(old)+1), old );
}

StrPtr PairToXMLStr(Str message, pairs p) {
  tags tag = TagPair(p);
  ids id = IdPair(p);
  Str msg = message ? message : "";
  Str format = message
? "%s"
: "";
// I tried with both of the next two lines, just in case: same behavior
//  char buffer[strlen(format) + strlen(msg) + 2 * 20]; // gcc extension
  char * buffer = palloc(strlen(format) + strlen(msg) + 2 * 20);
  sprintf(buffer, format, tag, id, msg);
  return NewStr(buffer);
}

FUNCTION_DEFINE(pair_in) {  // cstring -> pair
  PG_RETURN_INT32(0);
}

FUNCTION_DEFINE(pair_out) { // pair -> cstring
  PG_RETURN_CSTRING( PairToXMLStr( NULL, PG_GETARG_INT32(0) ) );
}


** gdb backtraces

# gdb bin/postgres data/core
GNU gdb 6.3
...
Core was generated by `postgres: greg pairs [local] SELECT
'.

Program terminated with signal 11, Segmentation fault.
...


***  gdb backtrace after SELECT ARRAY[ pair_tag_id(3, 4) ];
(gdb) backtrace
#0  0xb7d2a07d in memmove () from /lib/tls/libc.so.6
#1  0x0403 in ?? ()
#2  0x081ed694 in ArrayCastAndSet (src=138452140, typlen=1027,
typbyval=, typalign=105 'i',
dest=0x8409cac "\177\177\177\177~", '\177' ...)
at arrayfuncs.c:3673
#3  0x081ed92a in CopyArrayEls (array=,
values=0x8409ba4,
nulls=0x84