0

I am completely new to Ruby so my question may have quite a simple answer. However, I couldn't find an answer on stackoverflow. I have the following very simple Sinatra app:

# myapp.rb
require 'rubygems'
require 'sinatra'
require 'json'

range=(199..2000).step(1)

set :port, 8888

get '/hostname' do
  content_type :json
  return range.next.to_json
end

Sinatra is starting:

 ruby testsinatra.rb
== Sinatra/1.0 has taken the stage on 8888 for development with backup from WEBrick
[2014-09-11 08:43:18] INFO  WEBrick 1.3.1
[2014-09-11 08:43:18] INFO  ruby 1.8.7 (2011-06-30) [x86_64-linux]
[2014-09-11 08:43:18] INFO  WEBrick::HTTPServer#start: pid=8215 port=8888

and serving first request:

 curl -ks http://localhost:8888/hostname
199

but failing with an error at the second request:

RuntimeError - continuation called across threads:

 /usr/lib/ruby/1.8/generator.rb:131:in `call'
 /usr/lib/ruby/1.8/generator.rb:131:in `next'
 /usr/lib/ruby/1.8/generator.rb:189:in `next'
 testsinatra.rb:30:in `GET /hostname'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:863:in `call'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:863:in `route'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:521:in `instance_eval'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:521:in `route_eval'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:500:in `route!'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:497:in `catch'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:497:in `route!'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:476:in `each'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:476:in `route!'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:601:in `dispatch!'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:411:in `call!'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:566:in `instance_eval'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:566:in `invoke'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:566:in `catch'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:566:in `invoke'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:411:in `call!'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:399:in `call'
 /usr/lib/ruby/gems/1.8/gems/rack-1.5.2/lib/rack/showexceptions.rb:24:in `call'
 /usr/lib/ruby/gems/1.8/gems/rack-1.5.2/lib/rack/methodoverride.rb:21:in `call'
 /usr/lib/ruby/gems/1.8/gems/rack-1.5.2/lib/rack/commonlogger.rb:33:in `call'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:979:in `call'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:1003:in `synchronize'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:1003:in `synchronize'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:979:in `call'
 /usr/lib/ruby/gems/1.8/gems/rack-1.5.2/lib/rack/handler/webrick.rb:60:in `service'
 /usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
 /usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
 /usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
 /usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
 /usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
 /usr/lib/ruby/1.8/webrick/server.rb:95:in `start'
 /usr/lib/ruby/1.8/webrick/server.rb:92:in `each'
 /usr/lib/ruby/1.8/webrick/server.rb:92:in `start'
 /usr/lib/ruby/1.8/webrick/server.rb:23:in `start'
 /usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
 /usr/lib/ruby/gems/1.8/gems/rack-1.5.2/lib/rack/handler/webrick.rb:14:in `run'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/base.rb:946:in `run!'
 /usr/lib/ruby/gems/1.8/gems/sinatra-1.0/lib/sinatra/main.rb:25
 testsinatra.rb:27

Clearly, I'm missing something basic. Please advice.

pangpang
  • 8,581
  • 11
  • 60
  • 96
  • Any reason that you use a really old ruby version with a old sinatra version. If not i would recommend to upgrade to ruby 2.1 and sinatra 1.4.5 – Sir l33tname Sep 11 '14 at 14:04

1 Answers1

0

Testing the code gives:

FiberError at /hostname
fiber called across threads

You can find a related question here: Sharing an enumerator across threads . It seems that the Fiber code stores the ID of the first thread that made an access to the object, and immediately fails when another thread tries to do so. You apparently just can't share enumerators between threads, and must resort to different means.

Please also note that global variables might be accessed simultaneously by different threads and you should always use thread-safe objects or explicit locking.

Community
  • 1
  • 1
To마SE
  • 573
  • 8
  • 19