Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ctrl-c no longer stops webrick cleanly #35

Closed
stepheneb opened this issue Jul 11, 2010 · 8 comments
Closed

ctrl-c no longer stops webrick cleanly #35

stepheneb opened this issue Jul 11, 2010 · 8 comments

Comments

@stepheneb
Copy link

On my Mac 10.6.4 system webrick no longer processes ctrl-C interrupts properly using any rack including and after this commit

http://github.com/rack/rack/commit/e516d89ffcdad1c9d58432aaaff4a382ed3997e7

commit e516d89ffcdad1c9d58432aaaff4a382ed3997e7
Author: raggi <jftucker@gmail.com>
Date:   Tue Mar 23 19:29:44 2010 +0000

    Move trap(:INT) to Rack::Server and support optional Handler protocol where handlers may implement .shutdown to do pre-exit cleanup.

I have this problem starting webrick using sc-server (used with the sproutcore gem) and script/server (on rails 2.3.8).

sc-server is cleanly halted using ctrl-C using rack 1.2.1, thin and sproutcore gem v1.0.1046

$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin9.8.0]

$ gem list rack

*** LOCAL GEMS ***

rack (1.2.1)
rack-mount (0.6.3)
rack-test (0.5.3)

$ gem list thin

*** LOCAL GEMS ***

thin (1.2.7)

$ gem list sproutcore

*** LOCAL GEMS ***

sproutcore (1.0.1046)

$ sc-server
SproutCore v1.0.1046 Development Server
Starting server at http://0.0.0.0:4020 in debug mode
To quit sc-server, press Control-C
>> Thin web server (v1.2.7 codename No Hup)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4020, CTRL+C to stop
^C>> Stopping

If I uninstall thin and run sc-server again (which now uses webrick) I need to kill the process to stop it.

This version of rack works (from Mar 23 -- about 3.5 months after the release of rack 1.1.0):
http://github.com/rack/rack/commit/456fb5fc658fec45a07c765ef22b2ced935808b1

commit 456fb5fc658fec45a07c765ef22b2ced935808b1
Author: raggi <jftucker@gmail.com>
Date:   Tue Mar 23 19:23:43 2010 +0000

    Fix a bug in CGI detection

Using ctrl-C with webrick stops working on the next commit later that day:
http://github.com/rack/rack/commit/e516d89ffcdad1c9d58432aaaff4a382ed3997e7

I have the same problem using rails 2.3.8 and rack e516d89...

$ script/server -p 3001
=> Booting WEBrick
=> Rails 2.3.8 application starting on http://0.0.0.0:3001
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-07-11 19:36:44] INFO  WEBrick 1.3.1
[2010-07-11 19:36:44] INFO  ruby 1.9.1 (2010-01-10) [i386-darwin9.8.0]
[2010-07-11 19:36:44] INFO  WEBrick::HTTPServer#start: pid=79959 port=3001

Here's what the console reports when I enter ctrl-C:

^C[2010-07-11 19:36:47] ERROR SystemExit: exit
    /Users/stephen/.rvm/gems/ruby-1.9.1-p378/gems/rails-2.3.8/lib/commands/server.rb:106:in `exit'

I have to kill the process to stop the server.

If instead I start rails with thin ctrl-C works either using rack e516d89... or rack 1.2.1

$ thin start -p3001
>> Using rails adapter
>> Thin web server (v1.2.7 codename No Hup)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:3001, CTRL+C to stop
^C>> Stopping ...
@stepheneb
Copy link
Author

Here's a trivial rack app with a webrick handler that shows the issue:

require 'rack'
app = proc do |env|
  [200, { 'Content-Type' => 'text/html' }, 'hello from rack and webrick']
end
server = ::Rack::Handler::WEBrick
server.run app, :Port => 3002

Try typing ctrl-c in the console:

$ ruby hellorack.rb 
[2010-07-11 22:34:35] INFO  WEBrick 1.3.1
[2010-07-11 22:34:35] INFO  ruby 1.9.1 (2010-01-10) [i386-darwin9.8.0]
[2010-07-11 22:34:35] INFO  WEBrick::HTTPServer#start: pid=82455 port=3002
^C[2010-07-11 22:34:37] ERROR Interrupt: 
  /Users/stephen/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/webrick/server.rb:90:in `select'

An error is displayed but the program does not quit.

In this simple example the code at lib/rack/server.rb:208 is never executed and
no handler is actually registered for ctrl-c:

trap(:INT) do
  if server.respond_to?(:shutdown)
    server.shutdown
  else
    exit
  end
end

@raggi
Copy link
Member

raggi commented Jul 12, 2010

rails 2.3.8 is not designed to work with rack 1.2.1. The rails issue is subtle, it's related to gem_prelude.rb.
Prelude is the bain of my existence. Speak to ruby-core who should have removed this a long time ago.
The fundamental issue here is that Rails 2.3.8 depends on Rack 1.1.0, NOT 1.2.1, and its server scripts are designed to work with 1.1.0, not 1.2.1. Correct gem activation inside rubygems works to load 1.1.0, but gem_prelude.rb (included in ruby 1.9.x) is broken and violated dependency resolution, just pushing the latest version of all gems onto the load path at boot. This is incorrect unspecified behavior and is leading to the bug you see in rails.

As far as using the handler is concerned, no, Handlers should not enforce traps, I moved the trap code into Rack::Server as this is the only part of rack that is designed to be used as (note: not part of) a real server.

If you want to build a custom server using a rack handler yourself, you will need to write the traps yourself, just as you will need to write the daemonization yourself, and so on.

Your above trivial example can be simplified by just using:

Rack::Server.new(:app => proc { |env| ... }, :Port => 3002, :server => 'webrick').start

I would recommend users utilise this instead of writing their own server code unless they have a good reason not to, in which case they take on the requirement to do this.

It should be noted by the OP that this issue exists for all other Rack handlers prior to my patch, and that was the motivation behind it. The fact that webrick used to work was inconsistent with the rest, and that inconsistency could even be considered a bug.

Edit:

Actually, that's incorrect, sorry. You will need to supply a :config => path_to_config.ru instead of :app, I will fix this immediately.

@stepheneb
Copy link
Author

Thanks for the info.

Regarding Rails -- yeah I know about the rails/rack/gem_prelude mess. I was just testing rack 1.1.0+ on rails when I was trying to find out whether the problem stopping the sproutcore dev server with ctrl-c happened there also. I didn't know at first if it was a problem just with the sproutcore sc-server.

After I saw it on rails I then made a simple case with just the WebBrick Handler to demonstrate the problem.

Thin 1.2.7 does implement it's own ctrl-c trap handling (and special-cases for Windows) which is why ctrl-c can still be used to stop rails or the sproutcore dev server if thin is installed.
http://github.com/macournoyer/thin/blob/master/lib/thin/server.rb#L215

I haven't yet seen the problem report from the OP -- I just noticed the commit on Mar 23 when I decided to look into why folks couldn't stop sc-server with ctrl-c anymore.

The sc-server code preferentially selects the Thin handler over webrick if thin is installed. It could be modified to setup a trap handler if using rack > 1.1.0 AND using the webrick handler:
http://github.com/sproutit/sproutcore-abbot/blob/master/lib/sproutcore/rack/service.rb#L31

Perhaps it's only Thin that also sets up it's own trap handler so the logic would be to setup the trap handler for all adapters except for thin ..??

I just tried a simple example using Rack::Server.new. I thought it might use thin preferentially but with thin installed and not specifying the :server it started webrick.

The following is with rack 1.2.1+ (c73b474...) installed:

$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin9.8.0]

$ gem list thin

*** LOCAL GEMS ***

thin (1.2.7)

$ cat hellorack2.rb 
require 'rubygems'
require 'rack'
Rack::Server.new(:app => proc { |env| [200, { 'Content-Type' => 'text/html' }, 'hello from rack and webrick'] }, :Port => 3003).start[rack]$ 

$ ruby hellorack2.rb 
[2010-07-12 11:41:17] INFO  WEBrick 1.3.1
[2010-07-12 11:41:17] INFO  ruby 1.9.1 (2010-01-10) [i386-darwin9.8.0]
[2010-07-12 11:41:17] INFO  WEBrick::HTTPServer#start: pid=86000 port=3003
^C[2010-07-12 11:41:20] INFO  going to shutdown ...
[2010-07-12 11:41:20] INFO  WEBrick::HTTPServer#start done.

@raggi
Copy link
Member

raggi commented Jul 12, 2010

Yeah, from the looks of the sproutcore code they should be using Rack::Server rather than copying code out of rack almost ad-verbatim.

@alexch
Copy link

alexch commented Jan 19, 2011

I'm observing the bug on a pure Rack app (the Jasmine gem) that launches a server by calling

Rack::Handler.default.run(app, options)

...I suppose the correct behavior is to use

Rack::Server.start(options)

instead, no?

@raggi
Copy link
Member

raggi commented Jan 19, 2011

It's not a bug, this is by design. Handlers should not be installing traps, as handlers are just interface code, not application templates.

@alexch
Copy link

alexch commented Jan 20, 2011

Right -- I'm not saying this is a bug in Rack; I'm asking if you can confirm the correct way to launch a server from inside a Ruby program, so people will stop making this mistake.

(I suppose if I were feeling picky I could say it's a documentation bug. Is there any comprehensive Rack documentation yet, other than source code?)

@alexch
Copy link

alexch commented Jan 20, 2011

Spoke too soon: there is a bug in Rack that prevents the preferred client code from working. You can't pass in an app to Rack::Server.start or Rack::Server.new, even though the rdoc says you can. The fix is to add

@app = options[:app] if options && options[:app]

to Server#initialize. This fix has apparently been applied on master but hasn't been released yet (as of Rack 1.2.1).

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants