Skip to content

Repeatable, But Time Varying R GUI Crash (PR#13880)

4 messages · William Dunlap, Duncan Murdoch

#
On 8/6/2009 4:11 PM, Marilyn & Rich Short wrote:
I can confirm it in R-patched as well.  It happens on the very first 
time through if you set gctorture() on, so it looks like somewhere in 
there is a missing PROTECT, and the garbage collector is reclaiming 
something that it shouldn't.

I'll try to track it down, but I'm not sure how quick I'll be.  (My 
house is full of contractors right now, so not a very nice place to work.)

I don't know any workaround other than "avoid doing the buggy thing". 
But I can't tell you what that is....

Duncan Murdoch
#
On Linux with R-2.10.0(devel) valgrind shows:
==9777== Invalid read of size 1
==9777==    at 0x805DD5C: SETCAR (memory.c:2712)
==9777==    by 0x8156463: Rf_defineVar (envir.c:1353)
==9777==    by 0x80B3B16: RestoreToEnv (saveload.c:2022)
==9777==    by 0x80B4913: do_loadFromConn2 (saveload.c:2346)
==9777==    by 0x8065CF4: do_internal (names.c:1160)
==9777==    by 0x816629F: Rf_eval (eval.c:464)
==9777==    by 0x816815D: do_begin (eval.c:1244)
==9777==    by 0x816629F: Rf_eval (eval.c:464)
==9777==    by 0x8169853: Rf_applyClosure (eval.c:698)
==9777==    by 0x81661D7: Rf_eval (eval.c:508)
==9777==    by 0x816815D: do_begin (eval.c:1244)
==9777==    by 0x816629F: Rf_eval (eval.c:464)
==9777==  Address 0x4516A1B is 3 bytes inside a block of size 2,584
free'd
==9777==    at 0x40052A3: free (vg_replace_malloc.c:233)
==9777==    by 0x805B121: R_gc_internal (memory.c:784)
==9777==    by 0x805C1CF: Rf_allocVector (memory.c:2022)
==9777==    by 0x80B3AD2: RestoreToEnv (saveload.c:2017)
==9777==    by 0x80B4913: do_loadFromConn2 (saveload.c:2346)
==9777==    by 0x8065CF4: do_internal (names.c:1160)
==9777==    by 0x816629F: Rf_eval (eval.c:464)
==9777==    by 0x816815D: do_begin (eval.c:1244)
==9777==    by 0x816629F: Rf_eval (eval.c:464)
==9777==    by 0x8169853: Rf_applyClosure (eval.c:698)
==9777==    by 0x81661D7: Rf_eval (eval.c:508)
==9777==    by 0x816815D: do_begin (eval.c:1244)
==9777==
==9777== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- y
starting debugger
==9777== starting debugger with cmd: /usr/bin/gdb -nw /proc/9802/fd/1014
9802
GNU gdb Red Hat Linux (6.3.0.0-1.96rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host
libthread_db library "/lib/tls/libthread_db.so.1".

Attaching to program: /proc/9802/fd/1014, process 9802
SETCAR (x=0x5565da0, y=0x4516a18) at memory.c:2712
2712        CHECK_OLD_TO_NEW(x, y);
(gdb) up
#1  0x08156464 in Rf_defineVar (symbol=0x4f5eee0, value=0x4516a18,
    rho=0x559a77c) at envir.c:1353
1353                        SET_BINDING_VALUE(frame, value);
(gdb) list
1348            if (HASHTAB(rho) == R_NilValue) {
1349                /* First check for an existing binding */
1350                frame = FRAME(rho);
1351                while (frame != R_NilValue) {
1352                    if (TAG(frame) == symbol) {
1353                        SET_BINDING_VALUE(frame, value);
1354                        SET_MISSING(frame, 0);      /* Over-ride */
1355                        return;
1356                    }
1357                    frame = CDR(frame);
(gdb) up
#2  0x080b3b17 in RestoreToEnv (ans=0x54876b4, aenv=0x559a77c)
    at saveload.c:2022
2022            defineVar(TAG(a), CAR(a), aenv);
(gdb) list
2017        PROTECT(names = allocVector(STRSXP, cnt));
2018        cnt = 0;
2019        PROTECT(a = ans);
2020        while (a != R_NilValue) {
2021            SET_STRING_ELT(names, cnt++, PRINTNAME(TAG(a)));
2022            defineVar(TAG(a), CAR(a), aenv);
2023            if(R_seemsOldStyleS4Object(CAR(a)))
2024                warningcall(R_NilValue,
2025                            _("'%s' looks like a pre-2.4.0 S4
object: please recreate it"),
2026                            CHAR(PRINTNAME(TAG(a))));

It again complains about the call to R_seemsOldStyleS4Object().

Memory in 'a' may have been freed.  Shouldn't the
    PROTECT(a=ans)
be done earlier, when ans is allocated, instead of when
the pointer is copied?


Bill Dunlap
TIBCO Software Inc - Spotfire Division
wdunlap tibco.com
#
The following change to src/main/saveload.c seems to fix
the problem.  (I think problem2() has gotten past the place where
valgrind first complained, but it will be quite a while before it
is done.)  It just protects 'ans' before 'names' is allocated instead
of afterwards.

===================================================================
--- saveload.c  (revision 49063)
+++ saveload.c  (working copy)
@@ -2012,11 +2012,12 @@
     if (! isList(ans))
        error(_("loaded data is not in pair list form"));

+    PROTECT(ans);
     a = ans;
     while (a != R_NilValue) {a = CDR(a); cnt++;}
     PROTECT(names = allocVector(STRSXP, cnt));
     cnt = 0;
-    PROTECT(a = ans);
+    a = ans;
     while (a != R_NilValue) {
        SET_STRING_ELT(names, cnt++, PRINTNAME(TAG(a)));
        defineVar(TAG(a), CAR(a), aenv);

Bill Dunlap
TIBCO Software Inc - Spotfire Division
wdunlap tibco.com
#
William Dunlap wrote:
Thanks Bill!  I'll commit the fix in a few minutes, to R-devel and 
R-patched.

Duncan