cjheath/geoip

Out of range latitude and longitude

kenn opened this issue · 8 comments

kenn commented

I'm using this gem to retrieve lat/lon from the user's IP, like so:

city = GeoIP::DB.city(@user.ip)
@user.lat = city.try(:latitude)
@user.lng = city.try(:longitude)

But I'm getting incorrect values sporadically.

@user.ip => "182.249.223.182",
@user.lat => 1387.872 - #<BigDecimal:f5f9c04,'0.1387872E4',18(45)>,
@user.lng => 1387.9004 - #<BigDecimal:f5f93d0,'0.13879004E4',18(45)>

If I run the same query from console, it works as expected:

> city = GeoIP::DB.city('182.249.223.182')
> city.try(:latitude)
=> 36.0
> city.try(:longitude)
=> 138.0

So, I'm guessing it has something to do with long-running reuse of the same GeoIP instance? GeoIP::DB is initialized at boot, only once:

class GeoIP
  DB = GeoIP.new(Rails.root.join('some/path/to/GeoLiteCity.dat'))
end

Thoughts?

GeoIP is not thread-safe, because it seeks a file pointer and reads from that location multiple times for each lookup. If you are initialising it once, you should store the handle in thread-local storage.

kenn commented

I'm not using threads, just a regular Rails app on Unicorn, which is single threaded. Do I still need to assign it to thread-local?

Try it with a Mutex and see if you still get problems, but the behaviour you describe sounds very like a race.

kenn commented

Well, we don't have config.threadsafe! on production, which means all requests are inside Rack::Lock so it's already mutex'd.

Perhaps, but try it anyway. EventMachine can still flip things around, I believe.

kenn commented

Will try, but I doubt that's the direct cause. We're not using EventMachine either. (If you use EM you'd use Rainbows! instead of Unicorn) It's a vanilla Rails 3.2 app with Unicorn, which I believe is the most popular setup.

Ok, well then I have no idea... but a lot of folk are using GeoIP without problems, including long-running instances. If you can find a cause and/or a fix, I'll be happy to re-open this issue.

kenn commented

Yeah I had been using the gem for quite a while without problems, then the problem started to appear at some point. I'll update when I find something out. Thanks for your time!