Segmentation fault in volatile c function

Поиск
Список
Период
Сортировка
От Louise Grandjonc
Тема Segmentation fault in volatile c function
Дата
Msg-id 5FEFE970-6A6B-454E-A3C7-FFD0FAAFDABD@gmail.com
обсуждение исходный текст
Ответы Re: Segmentation fault in volatile c function  (Peter Geoghegan <pg@bowt.ie>)
Список pgsql-general
Hi,

I'm creating my first ever extension. The function that I'm trying to write takes the schema and name of a table, and
addsit in a table with all the tables the extension follows. 
In that table I want the schema, name and oid of the table.

I created a C function for that. Here is the code

```
Datum add_mygreat_table(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(add_mygreat_table);

Datum add_mygreat_table(PG_FUNCTION_ARGS) {
  char *tableSchema,
    *tableName;

  Oid tableNamespace,
    relationId;

  tableSchema = PG_GETARG_CSTRING(0);
  tableName = PG_GETARG_CSTRING(1);

  tableNamespace = get_namespace_oid(tableSchema, false);
  relationId = get_relname_relid(tableName, tableNamespace);

  if (relationId == NULL)
  {
    ereport(ERROR, (errmsg("could not create remote table: "
                           "relation does not exist")));
  }

  Datum values[3];
  bool isNulls[3];
  memset(isNulls, false, sizeof(isNulls));

  values[0] = CStringGetTextDatum(tableSchema);
  values[1] = CStringGetTextDatum(tableName);
  values[2] = ObjectIdGetDatum(relationId);

  Relation greatTable = table_open(MyGreatTablesRelationId(), RowExclusiveLock);

  HeapTuple tuple = heap_form_tuple(RelationGetDescr(greatTable), values, isNulls);

  /*
   * CatalogTupleInsert() is originally for PostgreSQL's catalog. However,
   * it is used at here for convenience.
   */
  CatalogTupleInsert(greatTable, tuple);

  table_close(greatTable, RowExclusiveLock);
  heap_freetuple(tuple);

  CommandCounterIncrement();

  ereport(NOTICE,
          (errmsg("Table %s is now a great table", tableName)));

  PG_RETURN_BOOL(true);
}
```


And in the sql I have

```
CREATE OR REPLACE FUNCTION mygreat.add_mygreat_table(cstring, cstring)
  RETURNS bool
  LANGUAGE C STRICT IMMUTABLE
AS '$libdir/mygreat',
$$add_mygreat_table$$;
```


Here is my problem, it works as expected when the table doesn't exist.

```
mygreat_test=# create extension hydra;

CREATE EXTENSION
mygreat_test=# select mygreat.add_mygreat_table('public', 'sampledata3');
ERROR:  could not create remote table: relation does not exist
```

However if the table exists it just completely crashes

```
hydra_test=# select hydra.add_remote_table('snowflake', 'public', 'sampledata2');
NOTICE:  Table sampledata2 is now a mygreat table
server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
```

I figured that it was because of the `IMMUTABLE` as the function does modify the database. And according to
documentation

```
IMMUTABLE indicates that the function cannot modify the database and always returns the same result when given the same
argumentvalues; t 
```

So I tried creating it as a `VOLATILE` function.


```
CREATE OR REPLACE FUNCTION hydra.add_remote_table(cstring, cstring)
  RETURNS bool
  LANGUAGE C STRICT VOLATILE
AS '$libdir/mygreat',
$$add_mygreat_table$$;
CREATE FUNCTION
```

But now it just always crashes, and what used to return the proper error message when ran against a table that doesn't
existnow returns 

```
mygreat_test=# select mygreat.add_mygreat_table('public', 'sampledata3');
server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
```

In the logs, for the latest, I get

```
2021-10-27 12:28:02.712 PDT [44115] LOG:  statement: select mygreat.add_mygreat_table('public', 'sampledata3');
2021-10-27 12:28:02.718 PDT [43936] LOG:  server process (PID 44115) was terminated by signal 11: Segmentation fault:
11
2021-10-27 12:28:02.718 PDT [43936] DETAIL:  Failed process was running: select mygreat.add_mygreat_table('public',
'sampledata3');
2021-10-27 12:28:02.719 PDT [43936] LOG:  terminating any other active server processes
```

What am I doing wrong? Can anyone help me with this?

Thank you!




В списке pgsql-general по дате отправления:

Предыдущее
От:
Дата:
Сообщение: jsonb: unwrapping text
Следующее
От: Peter Geoghegan
Дата:
Сообщение: Re: Segmentation fault in volatile c function