From mtmorgan at fhcrc.org  Sun Mar  3 19:11:00 2013
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Sun, 03 Mar 2013 10:11:00 -0800
Subject: [Rd] Missing PROTECT in mkPRIMSXP ?
Message-ID: <51339234.1030109@fhcrc.org>

The Bioconductor build for a package DirichletMultinomial on

   R Under development (unstable) (2013-02-26 r62077) -- "Unsuffered Consequences"

at

 
http://bioconductor.org/checkResults/devel/bioc-LATEST/DirichletMultinomial/george2-buildsrc.html

shows

* creating vignettes ... ERROR
...

Error: processing vignette ?DirichletMultinomial.Rnw? failed with diagnostics:
  chunk 21 (label = ROC-dmngroup)
Error in mapply(FUN = f, ..., SIMPLIFY = FALSE) :
   invalid primitive operation given for dispatch
Execution halted

I have not been able to reproduce this on other systems, but the basic approach 
to a simpler reproducible example is to install the DirichletMultinomial 
Bioconductor package and then

 > tools::buildVignettes(dir="DirichletMultinomial")

where the 'dir' argument points to the uncompressed tarball. There is C code in 
the package, but not reached by this code chunk. Attempts to simplify the code 
generally results in the error disappearing.

R -d valgrind -e "tools::buildVignettes(dir="DirichletMultinomial")"

does not reveal anything. The error does not occur with gctorture(TRUE); 
tools::buildVignettes(dir="DirichletMultinomial").



By setting a breakpoint at Rf_error and creating a back-trace

(gdb) bt
#0  Rf_error (
     format=0x7ffff7a7cef8 "invalid primitive operation given for dispatch")
     at /home/biocbuild/src/R-3.0.r62077/src/main/errors.c:741
#1  0x00007ffff793a7ed in R_possible_dispatch (call=0x164d5c0, op=0x4d772a0,
     args=0x53325d0, rho=0x5334428, promisedArgs=TRUE)
     at /home/biocbuild/src/R-3.0.r62077/src/main/objects.c:1414
#2  0x00007ffff7908463 in Rf_DispatchOrEval (call=0x164d5c0, op=0x4d772a0,
     generic=0x7ffff7a8b0ef "length", args=0x53325d0, rho=0x5334428,
     ans=0x7ffffffe45a0, dropmissing=0, argsevald=1)
     at /home/biocbuild/src/R-3.0.r62077/src/main/eval.c:2413
#3  0x00007ffff792c318 in do_mapply (call=0x164d5c0, op=<optimized out>,
     args=<optimized out>, rho=0x5334428)
     at /home/biocbuild/src/R-3.0.r62077/src/main/mapply.c:49
...

we get to

(gdb) l mapply.c:49
44                  /* Cache the .Primitive: unclear caching is worthwhile. */
45                  static SEXP length_op = NULL;
46                  if (length_op == NULL) length_op = R_Primitive("length");
47                  // DispatchOrEval() needs 'args' to be a pairlist
48                  SEXP ans, tmp2 = PROTECT(list1(tmp1));
49                  if (DispatchOrEval(call, length_op, "length", tmp2, rho, 
&ans, 0, 1))
50                      lengths[i] = (R_xlen_t) (TYPEOF(ans) == REALSXP ?
51                                               REAL(ans)[0] : asInteger(ans));
52                  UNPROTECT(1);
53              }

and it seems like length_op is somehow incorrect. Starting again with a 
breakpoint at mapply.c:46, and watching the memory location of length_op, once 
assigned, for a write at the address of length_op

(gdb) b mapply.c:46
(gdb) r
...
(gdb) p length_op
$11 = (SEXP) 0x4d772a0
(gdb) watch *0x4d772a0
(gdb) c

leads to

(gdb) c
Continuing.
Hardware watchpoint 4: *0x4d772a0

Old value = 8
New value = 0
Rf_allocSExp (t=<optimized out>)
     at /home/biocbuild/src/R-3.0.r62077/src/main/memory.c:2056
2056        TYPEOF(s) = t;

which is R writing a new SEXP to the length_op location, as though this location 
had been garbage collected.

Asking for R_Primitive("length") in mapply.c gets us to dstruct.c:60, where we 
end up at

     if (result == R_NilValue) {
	result = allocSExp(type);
	SET_PRIMOFFSET(result, offset);
     }
...
     return result;

which looks like the allocated SEXP is not added to the PrimCache vector, and 
hence available for garbage collection. Perhaps a patch is along the lines of

Index: dstruct.c
===================================================================
--- dstruct.c	(revision 62113)
+++ dstruct.c	(working copy)
@@ -59,6 +59,7 @@
      if (result == R_NilValue) {
  	result = allocSExp(type);
  	SET_PRIMOFFSET(result, offset);
+	SET_VECTOR_ELT(PrimCache, offset, result);
      }
      else if (TYPEOF(result) != type)
  	error("requested primitive type is not consistent with cached value");


Martin
-- 
Dr. Martin Morgan, PhD
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N.
PO Box 19024 Seattle, WA 98109



[Rd] Missing PROTECT in mkPRIMSXP ?
Martin Morgan