Process.detach cause sinatra-1.4.7 auto exit - ruby

here is my code:
class App < Sinatra::Base
get "/" do
pid =fork do
end
Process.detach(pid)
end
end
App.start!
when i curl localhost:4567, the server auto exit and the output is:
127.0.0.1 - - [13/Aug/2016:23:45:18 CST] "GET / HTTP/1.1" 200 0
- -> /
[2016-08-13 23:45:18] INFO WEBrick::HTTPServer#start done.
== Sinatra has ended his set (crowd applauds)
my environment is:
Linux Mint 17.3 Rosa
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
Why does Sinatra quit after just one request? I want it to keep running until I deliberately kill it.

It's not Process.detach that causes Sinatra to quit, but the fact that the forked process ends and runs its at_exit hooks, which shut down the server (though I'm not quite sure how that can leak from the child process to the parent).
There's a couple of simple ways to prevent this.
I prefer this set-and-forget solution:
configure do
disable :traps
end
The downside is that Ctrl-C causes a not-so-graceful exit.
Alternatively, add this to the beginning of any fork block:
settings.running_server = nil
The downside is that you need to remember to add this to all forked code.
You might also find someone suggesting at_exit { Process.exit! } in all fork blocks, but I think it's less reliable because other at_exit handlers could interfere with it.
Unfortunately, I don't see any configuration option in Sinatra that would fix forking and still allow graceful handling of Ctrl-C.

Related

What is the correct way to end a WEBrick server process after a timeout?

I'm trying to implement a small WEBrick server that ends itself when there are no requests after x number of seconds. However, I'm getting nowhere. My very first attempt at simply exiting after 2 seconds fails. Here's the simple code
that doesn't work.
server = WEBrick::HTTPServer.new(:Port => 8000)
WEBrick::Utils::TimeoutHandler.register(2, Timeout::Error)
server.start
I thought that would simply exit the process after 2 seconds. Here's what actually happens:
[2020-01-19 15:41:10] INFO WEBrick 1.4.2
[2020-01-19 15:41:10] INFO ruby 2.5.1 (2018-03-29) [x86_64-linux-gnu]
[2020-01-19 15:41:10] INFO WEBrick::HTTPServer#start: pid=16622 port=8000
[2020-01-19 15:41:12] ERROR Timeout::Error: execution timeout
/usr/lib/ruby/2.5.0/webrick/server.rb:170:in `select'
And then the process keeps running. I have to ctrl-c to end it.
What's the correct way to shut down a server and end the process after a timeout?

Thread deadlock on simple operations in pry

[Note: I "fixed" this problem by creating and using a new gemset. I'm still curious why the problem occurred but it is no longer blocking me.]
[I am aware that there is a similar issue at Deadlock in Ruby join(), but I have tried the timeout parameter suggested there and it does not help. I suspect there is a pry-specific problem not covered there.]
I am getting the error below when running the code below, but only when executed within a pry session. This code has not been changed and has been working fine for quite a while, and I have no idea why it's an issue just now. I am using pry version 0.11.3 on Ruby 2.5.1. Also, this code works fine when pasted into pry; it's not working in my wifi-wand application that launches pry in the context of one of its objects (gem install wifi-wand to install, https://github.com/keithrbennett/wifiwand is the project page).
domains = %w(google.com baidu.com)
puts "Calling dig on domains #{domains}..." if #verbose_mode
threads = domains.map do |domain|
Thread.new do
output = `dig +short #{domain}`
output.length > 0
end
end
threads.each(&:join)
[1] pry(#<WifiWand::CommandLineInterface>)> ci
Calling dig on domains ["google.com", "baidu.com"]...
fatal: No live threads left. Deadlock?
3 threads, 3 sleeps current:0x00007fbd13d0c5a0 main thread:0x00007fbd13d0c5a0
* #<Thread:0x00007fbd14069c20 sleep_forever>
rb_thread_t:0x00007fbd13d0c5a0 native:0x00007fff89c2b380 int:0
/Users/kbennett/work/wifi-wand/lib/wifi-wand/models/base_model.rb:89:in `join'
/Users/kbennett/work/wifi-wand/lib/wifi-wand/models/base_model.rb:89:in `each'
/Users/kbennett/work/wifi-wand/lib/wifi-wand/models/base_model.rb:89:in `block in connected_to_internet?'
/Users/kbennett/work/wifi-wand/lib/wifi-wand/models/base_model.rb:126:in `connected_to_internet?'
/Users/kbennett/work/wifi-wand/lib/wifi-wand/command_line_interface.rb:264:in `cmd_ci'
Strangely, the problem was fixed by uninstalling and reinstalling the awesome_print gem. I have no idea why.

ssh proxy script runs in ruby but not in jruby

I have a ruby script that uses the net::ssh gem.
Its a simple script to tunnel through a jump-off server to a destination box. The box is only visible to the jump-off server. Here is the script:
require 'net/ssh/proxy/command'
require "net/ssh"
class TestTunnel
def initialize
proxy = Net::SSH::Proxy::Command.new('ssh admin#10.10.10.10 nc %h %p 2>/dev/null')
p "proxy gotten"
Net::SSH.start("host1", "admin", :password => "admin", :proxy => proxy) do |ssh|
hostname = ssh.exec!("hostname")
p "In #{hostname}"
end
end
end
b=TestTunnel.new
The issue is the script runs in ruby but not in jruby. My framework runs off jruby so I need to use it with jruby.
My solution was to call a bash script from my jruby script to setup the tunnel and run commands there but I would rather have everything done within jruby.
Here are the errors I get:
~/src/main/ruby$ jruby --1.9 scripts/test_tunnel.rb
"proxy gotten"
IO::EAGAINWaitReadable: Resource temporarily unavailable - errno backtraces disabled; run with -Xerrno.backtrace=true to enable
And when I run in ruby:
~/src/main/ruby$ ruby scripts/test_tunnel.rb
"proxy gotten"
"In vz-int-api02\n"
~/src/main/ruby$
When I run with -Xerrno.backtrace=true I can see that jruby is 1.7.9 and I can see that its using ruby 1.9:
~/src/main/ruby$ jruby -Xerrno.backtrace=true --1.9 scripts/test_tunnel.rb
"proxy gotten"
IO::EAGAINWaitReadable: Resource temporarily unavailable -
read_nonblock at org/jruby/RubyIO.java:2856
recv at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/proxy/command.rb:75
fill at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/buffered_io.rb:65
next_packet at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/packet_stream.rb:88
poll_message at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:183
loop at org/jruby/RubyKernel.java:1519
poll_message at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:178
wait at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:215
loop at org/jruby/RubyKernel.java:1519
wait at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:213
initialize at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:87
start at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh.rb:207
initialize at scripts/test_tunnel.rb:8
(root) at scripts/test_tunnel.rb:15
~/src/main/ruby$ jruby -Xerrno.backtrace=true --1.9 --version
jruby 1.7.9 (1.9.3p392) 2013-12-06 87b108a on Java HotSpot(TM) 64-Bit Server VM 1.8.0_72-b15 +indy [linux-amd64]
~/src/main/ruby$
Is there any way to get this to run in jruby like it does in ruby or is my solution to call a bash script from within jruby the only way to do this?
A
This sounds a lot like this bug in net-ssh that was fixed in net-ssh 3.0.2.
The commit message that closed that issue t was "Bugfix: proxy command was using nonblocking io api incorrectly causing rare IO::EAGAIN errors" which sounds like exactly what you are getting.

EventMachine UNIX socket connections: how do I use them with Thin running as a service?

How can I use EventMachine.connect_unix_domain while running Thin as a service (using the init script (excerpt) and configuration below). The code directly below is the problem (I get an eventmachine not initialized: evma_connect_to_unix_server error). The second code example works, but doesn't allow me to daemonize thin (I don't think). Does Thin not already have a running instance of EventMachine?
UPDATE: Oddly enough: stopping the server (with service thin stop), seems to get into the config.ru file and run the app (so it works, until the stop command times out and kills the process). What happens when thin stops that could be causing this behavior?
Problematic Code
class Server < Sinatra::Base
# Webserver code removed
end
module Handler
def receive_data data
$received_data_changed = 1
$received_data = data
end
end
$sock = EventMachine.connect_unix_domain("/tmp/mysock.sock", Handler)
Working Code
EventMachine.run do
class Server < Sinatra::Base
# Webserver code removed
end
module Handler
def receive_data data
$received_data_changed = 1
$received_data = data
end
end
$sock = EventMachine.connect_unix_domain("/tmp/mysock.sock", Handler)
Server.run!(:port => 4567)
end
Init Script excerpt
DAEMON=/usr/local/bin/thin
SCRIPT_NAME=/etc/init.d/thin
CONFIG_PATH=/etc/thin
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
case "$1" in
start)
$DAEMON start --all $CONFIG_PATH
;;
Thin Config
---
chdir: /var/www
environment: development
timeout: 30
log: log/thin.log
pid: tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 512
require: []
wait: 30
servers: 1
socket: /tmp/thin.server.sock
daemonize: true
Thin is built on top of EventMachine. I think that you should use EventMachine for serving your app. Try to debug further way Thin won't daemonize. (What version are you using?). Also you can run Thin on another port such as 4000 and then pass that as the upstream server to your proxy-forwarding server, if that is what you want to achieve.
What I ended up doing was removing the EventMachine.run do ... end and simply enclosing the socket connection in an EM.next_tick{ $sock = EventMachine.connect_unix_domain("/tmp/mysock.sock", Handler) }.
Could swear I tried this once before... but it works now.
EDIT: Idea for next_tick came from here.

Ruby crashes on windows

I'm facing same problem described here: why-rails-fails-with-ruby-exe-has-encountered-a-problem-and-needs-to-close. that is ruby get crashed with following error:
ruby.exe has encountered a problem and needs to close. We are sorry for the inconvenience.
I'm asking this to add some details on it as that question was not asked by me I am not able to add information in it. So this is not duplicate.
Ruby crashes eventually no matter how I run it (in development or in production), but it seems to crash more often in production mode. Sometimes it will crash when I hold down the F5 key, but sometimes I have to hold and release it intermittently for a minute or two. It appears to be very dependent on timing, but I can usually make it crash in less than 60 seconds.
When I refresh the GET request is sent for 3 times as follows:
Started GET "/app/page" for 127.0.0.1 at 2011-02-23 10:57:35 +0530
Processing by AppController#page as HTML
Rendered pms/dashboard.html.erb within layouts/application (109.4ms)
Completed 200 OK in 141ms (Views: 140.6ms | ActiveRecord: 0.0ms)
Started GET "/app/page" for 127.0.0.1 at 2011-02-23 10:57:35 +0530
Processing by AppController#page as */*
Rendered pms/dashboard.html.erb within layouts/application (15.6ms)
Completed 200 OK in 187ms (Views: 187.5ms | ActiveRecord: 0.0ms)
Started GET "/app/page" for 127.0.0.1 at 2011-02-23 10:57:35 +0530
Processing by AppController#page as */*
Rendered pms/dashboard.html.erb within layouts/application (15.6ms)
Completed 200 OK in 219ms (Views: 218.7ms | ActiveRecord: 0.0ms)
And if I rapidly refresh the page get following error in one of or all the 3 request:
ERROR Errno:ECONNABORTED: An established connection was aborted by the software in your host machine:
c:/Ruby/lib/1.9.1/webrick/httpresponse.rb:323:in 'write'
c:/Ruby/lib/1.9.1/webrick/httprespose.rb:323:in '<<'
c:/Ruby/lib/1.9.1/webrick/httprespose.rb:323:in '_write_data'
c:/Ruby/lib/1.9.1/webrick/httprespose.rb:295:in 'send_body_string'
c:/Ruby/lib/1.9.1/webrick/httprespose.rb:186:in 'send_body'
c:/Ruby/lib/1.9.1/webrick/httprespose.rb:103:in 'send_response'
c:/Ruby/lib/1.9.1/webrick/httpserver.rb:86:in 'run'
ERROR Errno:ECONNABORTED: An established connection was aborted by the software in your host machine:
c:/Ruby/lib/1.9.1/webrick/httpserver.rb:56:in 'eof?'
c:/Ruby/lib/1.9.1/webrick/httpserver.rb:56:in 'run'
c:/Ruby/lib/1.9.1/webrick/server.rb:183:in 'block in start_thread'
INFO going to shutdown....
INFO WEBrick::HTTPServer#start done
When I started to get this error?
When I added images, css and javascript in my project I started to get this error. I also tried by removing one of this 3 and see who causes the error but every time my ruby.exe get crashed and i see the error:
ruby.exe has encountered a problem and needs to close. We are sorry for the inconvenience.
How can I solve this?
When I start server following is printed on console:
=>Booting WEBrick
=>Rails 3.0.3 application starting in development on http://0.0.0.0:3000
=>Call with -d to detach
=>Ctrl-C to shutdown server
[2011-02-23 10:59:22] INFO WEBrick 1.3.1
[2011-02-23 10:59:22] INFO ruby 1.9.2 (2010-08-18) [i386-mingw32]
[2011-02-23 10:59:22] INFO WEbrick::HTTPServer#start: pid:2448 port=3000
Output of ruby -v
ruby 1.9.2p0 (2010-08-18) [i386-mingw32]
... except the installer is now ALSO the crashing 1.9.2-p290
Workaround:
Add (or change)
config.log_level = :warn
in config/environments/development.rb
(not my solution - found it in another thread)
Running 1.9.2 on windows puts you in a REALLY small minority of users. If you don't have an explicit need for 1.9, I'd use 1.8.7. Specifically, I'd use the package from RailsInstaller: http://railsinstaller.org/
i got the same crashes on windows 7 with 1.9.2-p290. someone said to clear development.log file. i can't believe but after deleting my 12mb development.log everything works fine.
it is possible that a native (C) extension is failing and bringing the whole ruby down; in my case it was sql server adapter looping indefinitely/using whole heap; after we traced and fixed the bug in the adapter (https://github.com/rails-sqlserver/tiny_tds/pull/124) it does not fail again

Resources