I want to run the startdrb method concurrently with the printstuff method on a Windows system. I messed around with Thread.new but the service starts and terminates after the thread completes.
How would this be written?
require 'drb'
require 'drb/ssl'
class TestDRB
def dostuff
...
end
def startdrb
begin
config = {SSLCertName: [["CN","DRuby"]]}
DRb.start_service("drbssl://127.0.0.1:9911", BHRBeacon.new, config)
rescue Exception => e
puts e.full_message
end
def printstuff
begin
puts "this will run while Drb service is also running"
end
TestDRB.new.startdrb
TestDRB.new.printstuff
Related
I'm trying to run a Sinatra app in a new Thread in order to also run some other thing inside my script but when I do:
require 'sinatra/base'
class App < Sinatra::Base
...some routes...
end
Thread.new do
App.run!
end
Nothing happens and Sinatra server is not started. Is there anything I'm missing in order to achieve this?
Finally I run the other ruby process in a Thread but from Sinatra application and it works just fine.
class App < Sinatra::Base
threads = []
threads <<
Thread.new do
Some::Other::Thing
rescue StandardError => e
$stderr << e.message
$stderr << e.backtrace.join("\n")
end
trap('INT') do
puts 'trapping'
threads.each do |t|
puts 'killing'
Thread.kill t
end
end
run!
end
And I added a control when Sinatra app is exited also kill the open thread.
I have a jruby class which contains a heartbeat that does something every certain number of seconds: (simplified code below)
class Client
def initialise
#interval = 30
#heartbeat = Thread.new do
begin
loop do
puts "heartbeat"
sleep #interval
end
rescue Exception => e
Thread.main.raise e
end
end
end
end
And I have a range of rspec tests that instantiate this class.
At the end of each test, I would expect the object to be destroyed, but the threads seem to remain.
At the moment I've fixed this with:
client.rb:
def kill
#heartbeat.kill
end
rspec:
after(:all) do
client.kill
end
Which seems to do the job - but this doesn't feel like the best way to do it.
What is the best way to approach this?
Using version jruby-9.1.10.0 & rspec 3.7.0
Edit:
As per http://ruby-doc.org/core-2.4.0/Thread.html I would expect the thread to normally terminate when the main thread does
In my tests I instantiate the client with
describe Client do
context 'bla' do
let(:client) do
described_class.new
end
it 'blas' do
end
end
end
You should replace after(:all) with after(:each).
Should be the correct syntax for what you want to do because after(:all) evaluates after all test cases have been run.
Using EM::stop_server schedules the server to be stopped. How can I know when the server is actually stopped?
require 'eventmachine'
class TestServer < EM::Connection
def post_init
send_data "Welcome\r\n"
end
end
class TestClient < EM::Connection
def receive_data(data)
puts data
end
end
Thread.new do
EM.run { }
end
while !EM.reactor_running? ; end
g = EM::start_server('127.0.0.1', 6667, TestServer)
EM::stop_server(g)
#sleep(1)
EM::connect('127.0.0.1', 6667, TestClient)
sleep
Running the above outputs Welcome. However if I uncomment sleep(1), nothing is printed.
Is there a way to achieve something similar without using sleep? Like using EM.reactor_running? to check if EM reactor's has started but to check if a server has been stopped.
I am using AirBnb Nerve service. It's service code looks like this:
require 'logger'
require 'json'
require 'timeout'
require 'nerve/version'
require 'nerve/utils'
require 'nerve/log'
require 'nerve/ring_buffer'
require 'nerve/reporter'
require 'nerve/service_watcher'
module Nerve
class Nerve
include Logging
def initialize(opts={})
log.info 'nerve: starting up!'
# set global variable for exit signal
$EXIT = false
...some code...
# Any exceptions in the watcher threads should wake the main thread so
# that we can fail fast.
Thread.abort_on_exception = true
log.debug 'nerve: completed init'
end
def run
log.info 'nerve: starting run'
#services.each do |name, config|
launch_watcher(name, config)
end
begin
sleep
rescue StandardError => e
log.error "nerve: encountered unexpected exception #{e.inspect} in main thread"
raise e
ensure
$EXIT = true
log.warn 'nerve: reaping all watchers'
#watchers.each do |name, watcher_thread|
reap_watcher(name)
end
end
log.info 'nerve: exiting'
ensure
$EXIT = true
end
def launch_watcher(name, config)
... some code ...
end
def reap_watcher(name)
... some code ...
end
end
end
I do not see any stop method. What is the right way of stopping such a service? I am using JRuby and intend to write a JSVC adapter for this service.
There is no way to do this via the current API, short of sending it a signal.
If sending a signal isn't going to work and you want to handle stop explicitly, it looks like you will need to change the following things:
Add a #stop method to Nerve that sets $EXIT = true.
Modify #run so that rather than sleeping forever (sleep) it wakes up and checks $EXIT.
This is related to a question I asked here:
Thread Locking in Ruby (use of soap4r and QT)
However it is particular to one part of that question and is supported by a simpler example. The test code is:
require 'rubygems'
require 'thread'
require 'soap/rpc/standaloneserver'
class SOAPServer < SOAP::RPC::StandaloneServer
def initialize(* args)
super
# Exposed methods
add_method(self, 'test', 'x', 'y')
end
def test(x, y)
return x + y
end
end
myServer = SOAPServer.new('monitorservice', 'urn:ruby:MonitorService', 'localhost', 4004)
Thread.new do
puts 'Starting web services'
myServer.start
puts 'Ending web services'
end
sleep(4)
#Thread.new do
testnum = 0
while testnum < 4000 do
testnum += 1
puts myServer.test(0,testnum)
sleep(2)
end
#end
puts myServer.test(0,4001)
puts myServer.test(0,4002)
puts myServer.test(0,4003)
puts myServer.test(0,4004)
gets
When I run this with the thread commented out everything runs along fine. However, once the thread is put in the process hangs. I poked into Webrick and found that the stop occurs here (the puts are, of course, mine):
while #status == :Running
begin
puts "1.1"
if svrs = IO.select(#listeners, nil, nil, 2.0)
svrs[0].each{|svr|
puts "-+-"
#tokens.pop # blocks while no token is there.
if sock = accept_client(svr)
th = start_thread(sock, &block)
th[:WEBrickThread] = true
thgroup.add(th)
else
#tokens.push(nil)
end
}
end
puts ".+."
When run with the thread NOT commented out I get something like this:
Starting web services
1.1
.+.
1.1
4001
4002
4003
4004
1
.+.
1.1
If the problem is caused by the gets() call and the purpose of the gets() call in your code is to prevent the Ruby interpreter from exiting, you can replace it with Thread.join() calls for each thread that you create. Join() will block until that thread has finished executing and therefore it'll prevent the Ruby interpreter from exiting.
E.g.:
t1 = Thread.new do
puts 'Starting web services'
myServer.start
puts 'Ending web services'
end
t2 = ...
...
t1.join
t2.join
Alternatively, if you can join() only one of the threads if there is a single thread that controls the execution of the application, and the other threads will be killed on exit.
The trailing gets blocks Ruby's IO. I'm not sure why. If it is replaced with pretty much anything the program works. I used a sleeping loop:
loop do
sleep 1
end
ADDED:
I should note that I also get strange behavior with sleep based on the sleep increment. In the end I abandoned Ruby since the threading behavior was too wonky.