Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nan.h error on node v0.10.22 #67

Open
ashbrener opened this issue Nov 20, 2013 · 14 comments
Open

nan.h error on node v0.10.22 #67

ashbrener opened this issue Nov 20, 2013 · 14 comments

Comments

@ashbrener
Copy link

We are experiencing a new error (very infrequently) since upgrading to node v0.10.22. The following message is displayed and the process exits immediately.

node: /opt/pre-publish/star/node_modules/orion/node_modules/geoip/node_modules/nan/nan.h:809: bool _NanGetExternalParts(v8::Handle<v8::Value>, const char**, size_t*): Assertion `val->IsString()' failed.
Aborted

I suspect it may have something to do with the infamous WalMart memory leak on closed handles fix.

@kuno
Copy link
Owner

kuno commented Nov 22, 2013

thanks for report,

I'll take a look this weekend.

@kuno
Copy link
Owner

kuno commented Nov 22, 2013

@ashleybrener

What the version of geoip you are using?

@kuno
Copy link
Owner

kuno commented Dec 28, 2013

@ashleybrener

I've push some code in new unstable branch, can you give it a try?

@kuno
Copy link
Owner

kuno commented Jan 13, 2014

Not repeatable, Closing.

@kuno kuno closed this as completed Jan 13, 2014
@nfo
Copy link
Contributor

nfo commented Feb 12, 2014

For the ones having the issue, it can happen simply because the given IP is not a string, as said in the error message. For example null, a number, an object, a function, etc.
So it's way safer too always check the variable before calling lookup.

if (ip != null) && typeof ip === 'string'

But even with this check, I'm still having the issue randomly on geoip 0.5.0 to 0.5.2 and nodejs 0.8.18 and 0.10.21.

@kuno
Copy link
Owner

kuno commented Feb 13, 2014

@nfo

Actually, some days ago, I've merged a pull request to try to solved this issue.

In short words, what this patch did is, if the given parameter is not a string, it just throw an error.

You can clone the repo and give it a try.

Also, since you mention, you've experienced some issues, can you give me some examples?

I'd live add them in the unit tests.

@nfo
Copy link
Contributor

nfo commented Feb 13, 2014

@kuno Thanks for the answer. I tried the pull request, which does more or less what I did by hand, and I still have crashes. It happens approximatively once per minute, in a system that handles several thousands requests per second. I think it would be easier for me to patch nan.h to make it return false instead of calling assert. I mean, ok, I probably sent a bad value, but at least I should be able to deal with the error. What do you think ?
I don't have time right now to replay the requests to see which IP could have cause the problem. Or worse, perhaps it happen in certain conditions, on a certain setup, on a certain load.

(by the way, it would be nice explaining why using synchronous methods is the recommended way, in usage.md)

@nfo
Copy link
Contributor

nfo commented Feb 26, 2014

Context: I still have the C++ assert (& abort) even with the last commits, the ones that check that the given ip or domain is a string with the function isValidIpORdomain().

So here is what I did to prevent my nodejs processes to crash: nfo@7c2330c
What I did is calling the function IsString() in the C code of geoip, before it calls nan.h. If IsString() returns false, then the lookup functions return a null value.
I don't make a pull request because I'm pretty sure you don't want this commit as is.

Apparently typeof val == 'string' in JS and IsString() in C do not always return the same thing. I process several millions of IPs per hour from all over the world. I had a crash every 10 minute or so. After 3 hours with this "fix", I don't have any crash anymore, and my dashboards show that the data are still ok.

@kuno kuno reopened this Feb 27, 2014
@kuno
Copy link
Owner

kuno commented Feb 27, 2014

@nfo

Thanks for you comments,
Yes, I am lacks the experiences that you have that to run millions lookups.

I'll definitely implement your idea into code.

@kuno
Copy link
Owner

kuno commented Feb 27, 2014

@nfo

BTW, can you offer some details about the difference between

typeof val == 'string' in JS and IsString() in C

@nfo
Copy link
Contributor

nfo commented Feb 27, 2014

@kuno
I have to admit that I have no clue why IsString() is more restrictive, but I think it's not trolling if I say that we can never trust JS with these kind of stuff.

Perhaps you should call the IsString() function directly in isValidIpORdomain http://bespin.cz/~ondras/html/classv8_1_1Value.html#a14bd69255a9fd04fa641713188814958

Also I did not take the time trying to find which kind of value would make IsString() return false.

@kuno
Copy link
Owner

kuno commented Feb 27, 2014

@nfo

good idea, I think we can expose a c++ function in js land to validate inputs.

Thanks.

@kuno
Copy link
Owner

kuno commented Feb 28, 2014

@nfo

I've just add a natvie function isString to validate the put.

You can found committing details in here.

If you give it a try on your environment, I'll appreciated.

@kuno
Copy link
Owner

kuno commented Feb 28, 2014

@nfo

By default, if the given input is not a string, it will throw an error or call the callback with the first argument is the error object.

But if you created the instance with a extra options object, and set the key silent to true, it just return null even with inputs is not valid string. e.g

var city  = new geoip.City('/path/to/db', {silent: true});

city.lookupSync(null) === null;

city.lookup(null, function(err, data) {
    // err is null
   // data is null
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants