Ошибка Синатры - продолжение вызывается через потоки
Я совершенно новичок в Ruby, поэтому на мой вопрос может быть довольно простой ответ. Тем не менее, я не смог найти ответ на stackru. У меня есть следующее очень простое приложение Sinatra:
# 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
Синатра начинает:
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
и обслуживаем первый запрос:
curl -ks http://localhost:8888/hostname
199
но с ошибкой при втором запросе:
RuntimeError - продолжение вызывается между потоками:
/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
Понятно, что мне не хватает чего-то простого. Пожалуйста посоветуй.
1 ответ
Тестирование кода дает:
FiberError at /hostname
fiber called across threads
Вы можете найти связанный вопрос здесь: Разделение перечислителя между потоками. Кажется, что Fiber
В коде хранится идентификатор первого потока, который сделал доступ к объекту, и сразу же происходит сбой, когда другой поток пытается это сделать. По-видимому, вы просто не можете разделить перечислители между потоками и должны использовать разные средства.
Также обратите внимание, что к глобальным переменным могут обращаться разные потоки одновременно, и вы всегда должны использовать потоковые объекты или явную блокировку.