On Fri, Jul 5, 2013 at 5:18 PM, pagameba <[email protected]> wrote:
> The problem in full:
>
> I am working on updating node-mapserver that wraps the mapserver library in
> the class-refactor branch to a more maintainable code structure (basing my
> changes on the organization of node-ogr).
>
> Up to now, I have refactored the main module interface and started on the
> first class to be wrapped, a mapserver C struct called errorObj that I am
> wrapping with class MSError. The extension builds but I am facing is a
> runtime assertion error in the extension the first time I trigger a new
> MSError object to wrap an errorObj.
>
> Fatal error in ../deps/v8/src/api.h, line 297
> CHECK(allow_empty_handle || that != __null) failed
>
> With node 0.10 there is an extremely lengthy stack trace after this which
> can be seen in travis build 27.2. I couldn't find anything particularly
> useful in the stack trace.
>
> The extension builds and some tests pass (symbols and methods exported from
> the library itself), but fails when the library tries to create an Object
> that wraps a C object.
>
> In javascript, I call mapserver.getError(). In the extension, this invokes a
> mapserver methoderrorObj* err = msGetErrorObj();and returned with return
> scope.Close(MSError::New(err));. The New method of MSError does this:
>
> Handle<Value> MSError::New(errorObj *err) {
> HandleScope scope;
> MSError *wrapped = new MSError(err);
> Handle<Value> ext = External::New(wrapped);
> Handle<Object> obj = MSError::constructor->GetFunction()->NewInstance(1,
> &ext);
> return scope.Close(obj);
> }
>
> I have attempted to debug this using gdb, the best I can get out of it with
> my limited skills is that the error happens at this call:
>
> Handle<Object> obj = MSError::constructor->GetFunction()->NewInstance(1,
> &ext);
>
> What I can gather from this is that ext is null which means that the
> External::New(wrapped) call is not returning a valid value. I have confirmed
> that errorObj* err does point to a valid, properly initialized, errorObj
> structure. To clarify, there is no actual error, mapserver always returns a
> valid errorObj but with a code of 0 if there is no error at this time.
>
> Here is, hopefully, the relevant code.
>
> ms_error.hpp
>
> #ifndef __NODE_MS_ERROR_H__
> #define __NODE_MS_ERROR_H__
>
> #include <v8.h>
>
> #include <node.h>
> #include <node_object_wrap.h>
>
> #include <mapserver.h>
>
> using namespace v8;
> using namespace node;
>
> class MSError: public node::ObjectWrap {
> public:
> static Persistent<FunctionTemplate> constructor;
> static void Initialize(Handle<Object> target);
> static Handle<Value> New(const Arguments &args);
> static Handle<Value> New(errorObj *err);
>
> MSError();
> MSError(errorObj *err);
> inline errorObj *get() { return this_; }
>
> private:
> ~MSError();
> errorObj *this_;
> };
>
> #endif
>
> ms_error.cpp
>
> #include "ms_error.hpp"
>
> Persistent<FunctionTemplate> MSError::constructor;
>
> void MSError::Initialize(Handle<Object> target) {
> HandleScope scope;
>
> constructor =
> Persistent<FunctionTemplate>::New(FunctionTemplate::New(MSError::New));
> constructor->InstanceTemplate()->SetInternalFieldCount(1);
> constructor->SetClassName(String::NewSymbol("MSError"));
>
> //
> constructor->InstanceTemplate()->SetNamedPropertyHandler(MSError::NamedPropertyGetter,
> NULL, MSError::NamedPropertyQuery, NULL, MSError::NamedPropertyEnumerator);
>
> target->Set(String::NewSymbol("MSError"), constructor->GetFunction());
> }
>
> MSError::MSError(errorObj *err) : ObjectWrap(), this_(err) { }
>
> MSError::MSError() : ObjectWrap(), this_(0) { }
>
> MSError::~MSError() { }
>
> Handle<Value> MSError::New(const Arguments& args)
> {
> HandleScope scope;
>
> if (!args.IsConstructCall())
> return ThrowException(String::New("Cannot call constructor as function,
> you need to use 'new' keyword"));
>
> if (args[0]->IsExternal()) {
> Local<External> ext = Local<External>::Cast(args[0]);
> void *ptr = ext->Value();
> MSError *f = static_cast<MSError *>(ptr);
> f->Wrap(args.This());
> return args.This();
> }
>
> return args.This();
> }
That assertion you're hitting means there is an empty handle in your
code somewhere, e.g. obj or MSError::constructor. If the backtrace in
gdb points to this line:
> Handle<Object> obj = MSError::constructor->GetFunction()->NewInstance(1,
> &ext);
Then there's a couple of things you can do. `print
MSError::constructor` will tell you if it's actually pointing to
something. If gdb prints something like `{ val_ = 0 }`, then it's
empty. Same for ext.
You can add asserts in your code that check handles for validity, e.g.:
assert(handle.IsEmpty() == false); // handle should point to something
assert(handle->IsObject() == true); // handle should point to an object
One last thing: if the function that constructor->GetFunction() points
to throws an exception, the return value of NewInstance() will be an
empty handle. Same for out of memory conditions.
--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
---
You received this message because you are subscribed to the Google Groups
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.