I have been trying to use the Mozilla / SeaMonkey JavaScript library that ships with Ubuntu 16.04.3 LTS, mozjs185-1.0
, but am encountering a SIGSEGV
when I try to call JS_NewStringCopyN
twice to allocate two JSString
objects from char *
strings.
My sample code is as follows:
#include <js/jsapi.h>
#include <js/jscntxt.h>
#include <js/jscompartment.h>
size_t gStackChunkSize = 8192;
static void
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{ }
int main(int argc, char *argv[]) {
JSRuntime *rt = JS_NewRuntime(256L * 1024L * 1024L);
if (!rt)
return -1;
JSCompartment compartment(rt);
JSContext *cx = JS_NewContext(rt, gStackChunkSize);
if (!cx)
return -2;
JS_SetErrorReporter(cx, my_ErrorReporter);
cx->compartment = &compartment;
const char data[] = "PScript5.dll Version 5.2.2";
const char data2[] = "Thom Parker";
JSString *str = JS_NewStringCopyN(cx, data, sizeof(data));
JSString *str2 = JS_NewStringCopyN(cx, data2, sizeof(data2));
return 0;
}
Which I compile with:
g++ test.cpp -o mdntest -I/usr/include/nspr -lmozjs185-1.0 -L/usr/lib/x86_64-linux-gnu -lz -lnspr4 -lpthread
When I run ./mdntest
it generates a SIGSEGV
and crashes. Having debugged the 1.8.5 version of the Mozilla JavaScript library, I know that what is happening during the second call to JS_NewStringCopyN
is that the garbage collector is called (JS_gc
) and that somewhere it is trying to do a mark and sweep pass but is accessing some invalid memory, 30 levels deep in the back trace with a call to js::gc::ArenaBitmap::markIfUnmarked
.
My theory is there is some undocumented thing I'm forgetting do do after calling the first JS_NewStringCopyN
. Any advice or assistance would be greatly appreciated.
In the example code above, the issue I've found is that a JSCompartment
must be manually initialized before use.
Thus, by adding:
compartment.init();
right after the construction of compartment in JSCompartment compartment(rt);
the two JS_NewStringCopyN
are called without error and the garbage collector JS_gc
runs without error. Why the JSCompartment
doesn't call JSCompartment::init()
in its constructor and why this isn't clearly documented is beyond me.