<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,5 @@
 == 0.6.2 Rambo release
+ * Server now let current connections finish before stopping, fixes #18
  * Fix uploading hanging bug when body is moved to a tempfile,
    also delete the tempfile properly upon completion, fixes #25
  * 'thin restart' now sends HUP signals rather then stopping &amp; starting, closes #17</diff>
      <filename>CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,9 @@ module Thin
     # +true+ if the connection is on a UNIX domain socket.
     attr_accessor :unix_socket
     
+    # Server owning the connection
+    attr_accessor :server
+    
     def post_init
       @request  = Request.new
       @response = Response.new
@@ -48,6 +51,10 @@ module Thin
       @response.close rescue nil
     end
     
+    def unbind
+      @server.connection_finished(self)
+    end
+    
     protected
       def remote_address
         if remote_addr = @request.env[Request::FORWARDED_FOR]</diff>
      <filename>lib/thin/connection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,4 @@
 module Thin
-  # Raise when we require the server to stop
-  class StopServer &lt; Exception; end
-  
   # The Thin HTTP server used to served request.
   # It listen for incoming request on a given port
   # and forward all request to +app+.
@@ -42,13 +39,14 @@ module Thin
     #
     def initialize(host_or_socket, port=3000, app=nil, &amp;block)
       if host_or_socket.include?('/')
-        @socket = host_or_socket
+        @socket    = host_or_socket
       else      
-        @host   = host_or_socket
-        @port   = port.to_i
+        @host      = host_or_socket
+        @port      = port.to_i
       end       
-      @app      = app
-      @timeout  = 60 # sec
+      @app         = app
+      @timeout     = 60 # sec
+      @connections = []
       
       @app = Rack::Builder.new(&amp;block).to_app if block
     end
@@ -72,28 +70,41 @@ module Thin
       log   &quot;&gt;&gt; Thin web server (v#{VERSION::STRING} codename #{VERSION::CODENAME})&quot;
       trace &quot;&gt;&gt; Tracing ON&quot;
       
-      EventMachine.run do
-        begin
-          start_server
-        rescue StopServer
-          stop
-        end
-      end
+      EventMachine.run { @signature = start_server }
     end
     alias :start! :start
     
-    # Stops the server by stopping the listening loop.
+    # Stops the server after processing all current connections.
+    # Calling twice is the equivalent of calling &lt;tt&gt;stop!&lt;/tt&gt;.
     def stop
+      if @stopping
+        stop!
+      else
+        @stopping = true
+        
+        # Do not accept anymore connection
+        EventMachine.stop_server(@signature)
+        
+        unless wait_for_connections_and_stop
+          # Still some connections running, schedule a check later
+          EventMachine.add_periodic_timer(1) { wait_for_connections_and_stop }
+        end
+      end
+    end
+    
+    # Stops the server closing all current connections
+    def stop!
+      log &quot;&gt;&gt; Stopping ...&quot;
+
+      @connections.each { |connection| connection.close_connection }
       EventMachine.stop
+
       remove_socket_file
-    rescue
-      warn &quot;Error stopping : #{$!}&quot;
     end
     
-    # Stops the server by raising an error.
-    def stop!
-      raise StopServer
-    end    
+    def connection_finished(connection)
+      @connections.delete(connection)
+    end
     
     protected
       def start_server
@@ -117,14 +128,27 @@ module Thin
       end
       
       def initialize_connection(connection)
+        connection.server                  = self
         connection.comm_inactivity_timeout = @timeout
         connection.app                     = @app
         connection.silent                  = @silent
         connection.unix_socket             = !@socket.nil?
+
+        @connections &lt;&lt; connection
       end
       
       def remove_socket_file
         File.delete(@socket) if @socket &amp;&amp; File.exist?(@socket)
       end
+      
+      def wait_for_connections_and_stop
+        if @connections.empty?
+          stop!
+          true
+        else
+          log &quot;&gt;&gt; Waiting for #{@connections.size} connection(s) to finish, CTRL+C to force stop&quot;
+          false
+        end
+      end
   end
 end
\ No newline at end of file</diff>
      <filename>lib/thin/server.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,11 +10,11 @@ describe Server do
       body &lt;&lt; env['rack.input'].read
       [200, { 'Content-Type' =&gt; 'text/html', 'Content-Length' =&gt; body.size.to_s }, body]
     end
-    server = Thin::Server.new('0.0.0.0', 3333, app)
-    server.timeout = 3
-    server.silent = true
+    @server = Thin::Server.new('0.0.0.0', 3333, app)
+    @server.timeout = 3
+    @server.silent = true
     
-    @thread = Thread.new { server.start }
+    @thread = Thread.new { @server.start }
     sleep 0.1 until @thread.status == 'sleep'
   end
     
@@ -23,18 +23,18 @@ describe Server do
   end
   
   it 'should GET from TCPSocket' do
-    raw('0.0.0.0', 3333, &quot;GET /?this HTTP/1.1\r\n\r\n&quot;).
+    raw(&quot;GET /?this HTTP/1.1\r\n\r\n&quot;).
       should include(&quot;HTTP/1.1 200 OK&quot;,
                      &quot;Content-Type: text/html&quot;, &quot;Content-Length: &quot;,
                      &quot;Connection: close&quot;, &quot;this&quot;)
   end
   
   it 'should return empty string on incomplete headers' do
-    raw('0.0.0.0', 3333, &quot;GET /?this HTTP/1.1\r\nHost:&quot;).should be_empty
+    raw(&quot;GET /?this HTTP/1.1\r\nHost:&quot;).should be_empty
   end
   
   it 'should return empty string on incorrect Content-Length' do
-    raw('0.0.0.0', 3333, &quot;POST / HTTP/1.1\r\nContent-Length: 300\r\n\r\naye&quot;).should be_empty
+    raw(&quot;POST / HTTP/1.1\r\nContent-Length: 300\r\n\r\naye&quot;).should be_empty
   end
   
   it 'should POST from Net::HTTP' do
@@ -58,7 +58,40 @@ describe Server do
     get('/').should include('&quot;REMOTE_ADDR&quot;=&gt;&quot;127.0.0.1&quot;')
   end
   
+  it &quot;should wait for current requests before soft stopping&quot; do
+    socket = TCPSocket.new('0.0.0.0', 3333)
+    socket.write(&quot;GET / HTTP/1.1&quot;)
+    @server.stop # Stop the server in the middle of a request
+    socket.write(&quot;\r\n\r\n&quot;)
+    
+    out = socket.read
+    socket.close
+    
+    out.should_not be_empty
+  end
+  
+  it &quot;should not accept new requests when soft stopping&quot; do
+    socket = TCPSocket.new('0.0.0.0', 3333)
+    socket.write(&quot;GET / HTTP/1.1&quot;)
+    @server.stop # Stop the server in the middle of a request
+    
+    EventMachine.next_tick do
+      proc { get('/') }.should raise_error(Errno::ECONNRESET)
+    end
+    
+    socket.close
+  end
+  
+  it &quot;should drop current requests when hard stopping&quot; do
+    socket = TCPSocket.new('0.0.0.0', 3333)
+    socket.write(&quot;GET / HTTP/1.1&quot;)
+    @server.stop! # Force stop the server in the middle of a request
+    
+    EventMachine.next_tick { socket.should be_closed }
+  end
+  
   after do
+    @server.stop!
     @thread.kill
   end
   
@@ -67,8 +100,8 @@ describe Server do
       Net::HTTP.get(URI.parse('http://0.0.0.0:3333' + url))
     end
     
-    def raw(host, port, data)
-      socket = TCPSocket.new(host, port)
+    def raw(data)
+      socket = TCPSocket.new('0.0.0.0', 3333)
       socket.write data
       out = socket.read
       socket.close
@@ -143,11 +176,12 @@ describe Server, &quot;on UNIX domain socket&quot; do
   end
   
   it &quot;should remove socket file after server stops&quot; do
-    @server.stop
+    @server.stop!
     File.exist?('/tmp/thin_test.sock').should be_false
   end
   
   after do
+    @server.stop!
     @thread.kill
   end
   </diff>
      <filename>spec/server_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>dc607a67b9931ab6f1d9026e24e3311b49466c2f</id>
    </parent>
  </parents>
  <author>
    <name>macournoyer</name>
    <email>macournoyer@gmail.com</email>
  </author>
  <url>http://github.com/macournoyer/thin/commit/b6aa2a6e55acd25c77c217759789d5d9e8c2bc93</url>
  <id>b6aa2a6e55acd25c77c217759789d5d9e8c2bc93</id>
  <committed-date>2008-01-29T21:41:55-08:00</committed-date>
  <authored-date>2008-01-29T21:41:55-08:00</authored-date>
  <message>Server now let current connections finish before stopping, fixes #18</message>
  <tree>a7ac5e39326cf220e44ec07387b418965c03ce10</tree>
  <committer>
    <name>macournoyer</name>
    <email>macournoyer@gmail.com</email>
  </committer>
</commit>
