Alex Rivera | Logout

Can't stop WEBrick 1.3.1 with ctrl-c on Ubuntu 11.04

Asked 2011-05-05T01:01:59.600
33

I'm using RVM, Ruby 1.9.2, and Rails 3.0.7

A standard kill of the process from another terminal doesn't work, either, but kill -9 does, of course.

I found a similar question, CTRL+C to Webbrick server ignored, but it's unclear whether that question is describing the same underlying issue. Also, the resolution doesn't seem to apply, since I'm not using :git in my Gemfile.

update 1: (old now... see update 2, below, for the real scoop)

I managed to narrow the issue down to a single gem. If you source the following test script, you can see the issue, too (assuming you're on Ubuntu 11.04... there was no issue in 10.04)

rm -rf tmpkilltest

rvm 1.9.2
rvm --force gemset delete tmpkilltest
rvm gemset create tmpkilltest
rvm 1.9.2@tmpkilltest

gem install rails -v=3.0.7 --no-rdoc --no-ri
gem install sqlite3 -v=1.3.3 --no-rdoc --no-ri

rails new tmpkilltest

cd tmpkilltest

echo "gem 'barista', '1.0'" >> Gemfile

bundle

rails s

The fact that the issue is caused by Rails' interaction with a gem leads me to now believe that this question actually is related to CTRL+C to Webbrick server ignored, though the test case above shows that this one is clearly not caused by using :git for a gem.

update 2:

In update 1 I mentioned that I narrowed it down to a gem. When I went through that gem, I eventually found the real culprit. The gem was making a single system call. I've made a very minor modification to the test script where I no longer load the barista gem, but rather I simply append a single system call at the end of the application.rb. With that system call, ctrl-c doesn't work. Remove the system call and it does work.

rm -rf tmpkilltest

rvm 1.9.2
rvm --force gemset delete tmpkilltest
rvm 
Edit
Report

3 Answers

6

I believe ^C can't kill WEBrick servers because the server creates a new session:

In webrick/server.rb:

  class Daemon
    def Daemon.start
      exit!(0) if fork
      Process::setsid
      exit!(0) if fork
      Dir::chdir("/")
      File::umask(0)
      STDIN.reopen("/dev/null")
      STDOUT.reopen("/dev/null", "w")
      STDERR.reopen("/dev/null", "w")
      yield if block_given?
    end
  end

(Very similar code exists in rack/server.rb, so if you're starting WEBrick via rack, you might want to leave off the -D or --daemonize command line options.)

And from the setsid(2) manpage:

   setsid() creates a new session if the calling process is not
   a process group leader.  The calling process is the leader of
   the new session, the process group leader of the new process
   group, and has no controlling tty.

has no controlling tty means that signals generated by a terminal (^Z SIGTSTP, ^\ SIGKILL, SIGTTIN, SIGTTOU, etc.) can't reach the process even if it had been started on that terminal. The link has been severed.

answered 2011-05-05T01:52:31.160
6

Ok, the issue has been resolved for me. A recent kernel update, which I applied as part of Ubuntu's standard updates, fixed the problem.

Also, here is a good discussion of the issue, which explains that the root cause was a kernel regression introduced in 2.6.38 ( http://redmine.ruby-lang.org/issues/4777 )

The regression was patched, and it looks like the patch recently made it into Ubuntu's updates, so if you're being affected by this issue, you should apply the latest updates.

answered 2011-07-20T21:49:01.857
1

I had the same problem when updating my Ubuntu. Impossible to quit normally webrick using Ctrl+C, had to use kill -9...

answered 2011-05-24T10:02:19.573

Your Answer