libpq causes segfault when share library unloaded - Mailing list pgsql-bugs
From | Jim Studt |
---|---|
Subject | libpq causes segfault when share library unloaded |
Date | |
Msg-id | 199911041702.LAA22180@core.federated.com Whole thread Raw |
Responses |
Re: [BUGS] libpq causes segfault when share library unloaded
|
List | pgsql-bugs |
============================================================================ POSTGRESQL BUG REPORT TEMPLATE ============================================================================ Your name : Jim Studt Your email address : jim@federated.com System Configuration --------------------- Architecture (example: Intel Pentium) : Intel Pentium Operating System (example: Linux 2.0.26 ELF) : Linux 2.2.13 PostgreSQL version (example: PostgreSQL-6.5.2): PostgreSQL-6.5.2 Compiler used (example: gcc 2.8.0) : gcc 2.95.2 19991024 Please enter a FULL description of your problem: ------------------------------------------------ libpq will define an environment variable for PGCLIENTENCODING if none is specified. If libpq is a shared library that is dynamically loaded, and it is subsequently unloaded then it leaves an entry in the environ array pointing into unmapped memory which will cause a segfault the next time the environment array is traversed. Please describe a way to repeat the problem. Please try to provide a concise reproducible example, if at all possible: ---------------------------------------------------------------------- /* ** program to demonstrate segfault from a putenv in a ** dynamicall loaded library. ** Build with something like: make breaklibpq LDLIBS=-ldl ** DO NOT link to libpq. */ #include <postgresql/libpq-fe.h> #include <dlfcn.h> #include <stdio.h> #include <stdlib.h> main() { typedef PGconn *(*ConnFunc)(); typedef int(*PQstatusType)(); void *dl; ConnFunc func; PGconn *conn; PQstatusType statfunc; printf("initially getenv(PGCLIENTENCODING) is %08x\n", getenv("PGCLIENTENCODING")); /* load the libpq dynamically */ dl = dlopen("libpq.so",RTLD_NOW); if ( !dl) { fprintf(stderr,"Failed to open libpq: %s\n", dlerror()); exit(1); } /* find PQconnectdb */ func = (ConnFunc)dlsym(dl,"PQconnectdb"); if ( !func) { fprintf(stderr,"Failed to find PQconnectdb in libpq: %s\n", dlerror()); exit(1); } /* find PQstatus */ statfunc = (PQstatusType)dlsym(dl,"PQstatus"); if ( !statfunc) { fprintf(stderr,"Failed to find PQstatus in libpq: %s\n", dlerror()); exit(1); } /* call PQconnectdb */ conn = (*func)("dbname=template1"); if ( !conn || (*statfunc)(conn) == CONNECTION_BAD) { fprintf(stderr,"Failed to connect to template1\n"); exit(1); } printf("after connect getenv(PGCLIENTENCODING) is %08x\n", getenv("PGCLIENTENCODING")); /* close the library, as reference this will unmap it */ dlclose(dl); /* we should segfault in the upcoming getenv() call */ printf("after close getenv(PGCLIENTENCODING) is %08x\n", getenv("PGCLIENTENCODING")); } If you know how this problem might be fixed, list the solution below: --------------------------------------------------------------------- A library should either find a way to clean up its putenv changes when unloaded or not make them. I would lean toward keeping the client encoding in a global variable for use within libpq (its only used once over in PQmblen(). If it needs to be exposed to the client then an API call should be added. It may be possible to use special linker sections to arrange for cleanup code when a library is unloaded, like C++ static destructors use on some systems. This would probably be a portability nightmare. -- Jim Studt, President The Federated Software Group, Inc.
pgsql-bugs by date: