首页 > 解决方案 > 调用用 C 编写的 Postgres 函数时出现分段错误,导致 Postgres 服务器崩溃

问题描述

我有一个用 C 代码编写的 postgresql 函数。

当我尝试运行它时,我在我的postgresql-9.5-main.log文件中得到了这个:

2021-02-28 17:28:00 CST [1393-180] LOG:  server process (PID 31043) was terminated by signal 11: Segmentation fault

在 中psql,这是我收到的消息:

server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.

这也会使任何其他使用 Postgres 的程序崩溃。不过,Postgres 会立即重新启动。

我也试过在 13.1 服务器上运行它,并且发生了同样的错误。

构建函数的代码psql

CREATE OR REPLACE FUNCTION
 int_to_id(BIGINT)
 RETURNS TEXT AS 'int_to_id',
 'int_to_id'
LANGUAGE 'c' 
STRICT;

现在,我已验证代码生成了正确的 ID,但在最后一步中失败了。当我result用常量字符串替换时也是这种情况,比如"HELLO". 我想知道我的代码是否有问题,或者是否还有其他错误

C代码如下:

#include "postgres.h"
#include "fmgr.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

const char charmap[36] = {
    '0',
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    'a',
    'b',
    'c',
    'd',
    'e',
    'f',
    'g',
    'h',
    'i',
    'j',
    'k',
    'l',
    'm',
    'n',
    'o',
    'p',
    'q',
    'r',
    's',
    't',
    'u',
    'v',
    'w',
    'x',
    'y',
    'z'
};

Datum int_to_id(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(int_to_id);

Datum int_to_id(PG_FUNCTION_ARGS){
    char result[11] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
    int64 x =  PG_GETARG_INT64(0);
    long base_val = 1L;
    for (int i = 1; i <= 10; i++){
        
        if (x > base_val - 1L || i == 1){
           result[10 - i] = charmap[ ((int)(x / base_val)) % 36];
        } 
        base_val = base_val * 36L;
    }

    text * textval = cstring_to_text(result);
    PG_RETURN_TEXT_P(textval);
}

我的脚本生成文件:

MODULES = int_to_id

PG_CONFIG = pg_config
PGXS = $(shell $(PG_CONFIG) --pgxs)
INCLUDEDIR = $(shell $(PG_CONFIG) --includedir-server)
LIBDIR = $(shell pg_config --pkglibdir)
FCFLAGS = -fPIC
include $(PGXS)

clean: 
    rm *.o
    rm *.so

int_to_id.so: int_to_id.o
    cc  -shared -o int_to_id.so int_to_id.o

int_to_id.o: int_to_id.c
    cc ${FCFLAGS} -o int_to_id.o -c int_to_id.c $(CRFLAGS) -I $(INCLUDEDIR) 

install:
    $(shell cp int_to_id.so ${LIBDIR})

标签: cpostgresqlsegmentation-fault

解决方案


当我执行那个Makefile时,我得到:

Makefile:11: warning: overriding recipe for target 'clean'
/usr/pgsql-13/lib/pgxs/src/makefiles/pgxs.mk:342: warning: ignoring old recipe for target 'clean'
Makefile:21: warning: overriding recipe for target 'install'
/usr/pgsql-13/lib/pgxs/src/makefiles/pgxs.mk:241: warning: ignoring old recipe for target 'install'
cc -fPIC -o int_to_id.o -c int_to_id.c  -I /usr/pgsql-13/include/server 
int_to_id.c: In function ‘int_to_id’:
int_to_id.c:63:22: warning: implicit declaration of function ‘cstring_to_text’ [-Wimplicit-function-declaration]
   63 |     text * textval = cstring_to_text(result);
      |                      ^~~~~~~~~~~~~~~
int_to_id.c:63:22: warning: initialization of ‘text *’ {aka ‘struct varlena *’} from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
cc  -shared -o int_to_id.so int_to_id.o
/usr/lib64/ccache/clang -Wno-ignored-attributes -fno-strict-aliasing -fwrapv -O2  -I. -I./ -I/usr/pgsql-13/include/server -I/usr/pgsql-13/include/internal  -D_GNU_SOURCE -I/usr/include/libxml2  -I/usr/include -flto=thin -emit-llvm -c -o int_to_id.bc int_to_id.c
int_to_id.c:63:22: warning: implicit declaration of function 'cstring_to_text' is invalid in C99 [-Wimplicit-function-declaration]
    text * textval = cstring_to_text(result);
                     ^
int_to_id.c:63:12: warning: incompatible integer to pointer conversion initializing 'text *' (aka 'struct varlena *') with an expression of type 'int' [-Wint-conversion]
    text * textval = cstring_to_text(result);
           ^         ~~~~~~~~~~~~~~~~~~~~~~~
2 warnings generated.

这意味着您忘记包含定义的标题cstring_to_text

#include "utils/builtins.h"

之后,该函数在我的 PostgreSQL v13 上没有崩溃,但我没有对其进行广泛测试。

您不应clean覆盖install.Makefile


推荐阅读