Hello,
I've been struggling with a problem for the past several weeks, trying
to get PL/R (R procedural language handler for PostgreSQL,
http://www.joeconway.com/plr/) to work on Red Hat 9. In brief, R dumps
core during the embedded library initialization, while in Rf_regcomp(),
working on on Rprofile. Below I've included the important parts of a
backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x420b655c in re_compile_fastmap_iter () from /lib/tls/libc.so.6
(gdb) bt
#0 0x420b655c in re_compile_fastmap_iter () from /lib/tls/libc.so.6
#1 0x420b649d in re_compile_fastmap () from /lib/tls/libc.so.6
#2 0x403fcb3c in Rf_regcomp (preg=0xbfffb0e0, pattern=0x8ba68a0
"[[:blank:]]*([[:alnum:]]+)", cflags=0) at regex.c:5729
{...snipped...]
#32 0x403b1015 in R_ReplFile (fp=0x83250d8, rho=0x8321e30, savestack=0,
browselevel=0) at main.c:80
#33 0x403b17aa in R_LoadProfile (fparg=0x0, env=0x8321e30) at main.c:385
#34 0x403b1984 in setup_Rmainloop () at main.c:503
#35 0x4045c78f in Rf_initEmbeddedR (argc=4, argv=0xbfffcdb0) at system.c:332
From the backtrace it is apparent that re_compile_fastmap() is being
resolved to /lib/tls/libc.so.6 instead of the function by the same name
in R's regex.c. On the advice of Ulrich Drepper (of the Red Hat glibc
team) I was able to get a trace of the symbol resolution process:
# start PostgreSQL with glibc debugging turned on
env LD_DEBUG=all LD_DEBUG_OUTPUT=/home/postgres/dbg.out pg_ctl start
On Red Hat 8 (where everything works), the relevant output looks like this:
19097: symbol=re_compile_fastmap; lookup in file=postgres: postgres
regression [local] SELECT
19097: symbol=re_compile_fastmap; lookup in file=/usr/lib/libz.so.1
19097: symbol=re_compile_fastmap; lookup in
file=/usr/lib/libreadline.so.4
19097: symbol=re_compile_fastmap; lookup in file=/lib/libtermcap.so.2
19097: symbol=re_compile_fastmap; lookup in file=/lib/libcrypt.so.1
19097: symbol=re_compile_fastmap; lookup in file=/lib/libresolv.so.2
19097: symbol=re_compile_fastmap; lookup in file=/lib/libnsl.so.1
19097: symbol=re_compile_fastmap; lookup in file=/lib/libdl.so.2
19097: symbol=re_compile_fastmap; lookup in file=/lib/i686/libm.so.6
19097: symbol=re_compile_fastmap; lookup in file=/lib/i686/libc.so.6
19097: symbol=re_compile_fastmap; lookup in file=/lib/ld-linux.so.2
19097: symbol=re_compile_fastmap; lookup in
file=/usr/local/pgsql/lib/plr.so
19097: symbol=re_compile_fastmap; lookup in
file=/usr/local/lib/R/bin/libR.so
19097: binding file /usr/local/lib/R/bin/libR.so to
/usr/local/lib/R/bin/libR.so:
normal symbol `re_compile_fastmap'
On Red Hat 9 (where I get core dumps), the relevant output looks like this:
23521: symbol=re_compile_fastmap; lookup in file=postgres: postgres
regression [local] SELECT
23521: symbol=re_compile_fastmap; lookup in file=/usr/lib/libz.so.1
23521: symbol=re_compile_fastmap; lookup in
file=/usr/lib/libreadline.so.4
23521: symbol=re_compile_fastmap; lookup in file=/lib/libtermcap.so.2
23521: symbol=re_compile_fastmap; lookup in file=/lib/libcrypt.so.1
23521: symbol=re_compile_fastmap; lookup in file=/lib/libresolv.so.2
23521: symbol=re_compile_fastmap; lookup in file=/lib/libnsl.so.1
23521: symbol=re_compile_fastmap; lookup in file=/lib/libdl.so.2
23521: symbol=re_compile_fastmap; lookup in file=/lib/tls/libm.so.6
23521: symbol=re_compile_fastmap; lookup in file=/lib/tls/libc.so.6
23521: binding file /usr/local/lib/R/bin/libR.so to
/lib/tls/libc.so.6: normal symbol `re_compile_fastmap'
The problem exists when using both the 1.6.2 and 1.7.0 versions of
libR.so. I have been unable to find a way to prevent this behavior on
Red Hat 9 without patching R itself. The attached patch fixes the
problem, hopefully in the least obtrusive way. It declares the
internal-use-only regex.c functions 'static' instead of
'extern'. There
is also a small correction to eval-etc.Rout.save which had an old copyright.
The patch is against 1.7.0, compiles cleanly, and passes `make check` on
my Red Hat 9 machine. I'd appreciate it if you would consider it for
inclusion in R-devel, and for any future R.1.7.x release. If a patch
against R-devel is needed, I'd be happy to provide that. Alternatively,
if someone can suggest a fix that I can apply directly to PL/R, I would
also be most appreciative.
Thank you,
Joe
-------------- next part --------------
diff -cNr R-1.7.0/src/main/Rregex.h R-1.7.0.fixed/src/main/Rregex.h
*** R-1.7.0/src/main/Rregex.h Fri May 10 00:11:47 2002
--- R-1.7.0.fixed/src/main/Rregex.h Mon Apr 28 10:19:50 2003
***************
*** 452,463 ****
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
! extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
/* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */
! extern const char *re_compile_pattern
_RE_ARGS ((const char *pattern, size_t length,
struct re_pattern_buffer *buffer));
--- 452,463 ----
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
! static reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
/* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */
! static const char *re_compile_pattern
_RE_ARGS ((const char *pattern, size_t length,
struct re_pattern_buffer *buffer));
***************
*** 465,471 ****
/* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an
internal error. */
! extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
/* Search in the string STRING (with length LENGTH) for the pattern
--- 465,471 ----
/* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an
internal error. */
! static int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
/* Search in the string STRING (with length LENGTH) for the pattern
***************
*** 473,486 ****
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
! extern int re_search
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, int range, struct re_registers *regs));
/* Like `re_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
! extern int re_search_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, int range, struct re_registers *regs, int stop));
--- 473,486 ----
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
! static int re_search
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, int range, struct re_registers *regs));
/* Like `re_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
! static int re_search_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, int range, struct re_registers *regs, int stop));
***************
*** 488,500 ****
/* Like `re_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
! extern int re_match
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, struct re_registers *regs));
/* Relates to `re_match' as `re_search_2' relates to `re_search'.
*/
! extern int re_match_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, struct re_registers *regs, int stop));
--- 488,500 ----
/* Like `re_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
! static int re_match
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, struct re_registers *regs));
/* Relates to `re_match' as `re_search_2' relates to `re_search'.
*/
! static int re_match_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, struct re_registers *regs, int stop));
***************
*** 512,518 ****
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
! extern void re_set_registers
_RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
unsigned num_regs, regoff_t *starts, regoff_t *ends));
--- 512,518 ----
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
! static void re_set_registers
_RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
unsigned num_regs, regoff_t *starts, regoff_t *ends));
diff -cNr R-1.7.0/src/main/regex.c R-1.7.0.fixed/src/main/regex.c
*** R-1.7.0/src/main/regex.c Fri May 31 19:35:50 2002
--- R-1.7.0.fixed/src/main/regex.c Mon Apr 28 10:22:30 2003
***************
*** 991,997 ****
The argument SYNTAX is a bit mask comprised of the various bits
defined in regex.h. We return the old syntax. */
! reg_syntax_t
re_set_syntax (syntax)
reg_syntax_t syntax;
{
--- 991,997 ----
The argument SYNTAX is a bit mask comprised of the various bits
defined in regex.h. We return the old syntax. */
! static reg_syntax_t
re_set_syntax (syntax)
reg_syntax_t syntax;
{
***************
*** 3205,3211 ****
Returns 0 if we succeed, -2 if an internal error. */
! int
re_compile_fastmap (bufp)
struct re_pattern_buffer *bufp;
{
--- 3205,3211 ----
Returns 0 if we succeed, -2 if an internal error. */
! static int
re_compile_fastmap (bufp)
struct re_pattern_buffer *bufp;
{
***************
*** 3511,3517 ****
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
! void
re_set_registers (bufp, regs, num_regs, starts, ends)
struct re_pattern_buffer *bufp;
struct re_registers *regs;
--- 3511,3517 ----
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
! static void
re_set_registers (bufp, regs, num_regs, starts, ends)
struct re_pattern_buffer *bufp;
struct re_registers *regs;
***************
*** 3541,3547 ****
/* Like re_search_2, below, but only one string is specified, and
doesn't let you say where to stop matching. */
! int
re_search (bufp, string, size, startpos, range, regs)
struct re_pattern_buffer *bufp;
const char *string;
--- 3541,3547 ----
/* Like re_search_2, below, but only one string is specified, and
doesn't let you say where to stop matching. */
! static int
re_search (bufp, string, size, startpos, range, regs)
struct re_pattern_buffer *bufp;
const char *string;
***************
*** 3577,3583 ****
found, -1 if no match, or -2 if error (such as failure
stack overflow). */
! int
re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs,
stop)
struct re_pattern_buffer *bufp;
const char *string1, *string2;
--- 3577,3583 ----
found, -1 if no match, or -2 if error (such as failure
stack overflow). */
! static int
re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs,
stop)
struct re_pattern_buffer *bufp;
const char *string1, *string2;
***************
*** 3802,3808 ****
#ifndef emacs /* Emacs never uses this. */
/* re_match is like re_match_2 except it takes only a single string. */
! int
re_match (bufp, string, size, pos, regs)
struct re_pattern_buffer *bufp;
const char *string;
--- 3802,3808 ----
#ifndef emacs /* Emacs never uses this. */
/* re_match is like re_match_2 except it takes only a single string. */
! static int
re_match (bufp, string, size, pos, regs)
struct re_pattern_buffer *bufp;
const char *string;
***************
*** 3848,3854 ****
failure stack overflowing). Otherwise, we return the length of the
matched substring. */
! int
re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
struct re_pattern_buffer *bufp;
const char *string1, *string2;
--- 3848,3854 ----
failure stack overflowing). Otherwise, we return the length of the
matched substring. */
! static int
re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
struct re_pattern_buffer *bufp;
const char *string1, *string2;
***************
*** 5525,5531 ****
We call regex_compile to do the actual compilation. */
! const char *
re_compile_pattern (pattern, length, bufp)
const char *pattern;
size_t length;
--- 5525,5531 ----
We call regex_compile to do the actual compilation. */
! static const char *
re_compile_pattern (pattern, length, bufp)
const char *pattern;
size_t length;
diff -cNr R-1.7.0/tests/eval-etc.Rout.save
R-1.7.0.fixed/tests/eval-etc.Rout.save
*** R-1.7.0/tests/eval-etc.Rout.save Tue Apr 2 06:15:19 2002
--- R-1.7.0.fixed/tests/eval-etc.Rout.save Mon Apr 28 10:01:37 2003
***************
*** 1,6 ****
! R : Copyright 2002, The R Development Core Team
! Version 1.5.0 Under development (unstable) (2002-04-02)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
--- 1,6 ----
! R : Copyright 2003, The R Development Core Team
! Version 1.7.0 (2003-04-16)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.