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.


Reply via email to