How to stop the rack when client disconnect?

55 views
Skip to first unread message

JiangMiao

unread,
Apr 3, 2009, 9:56:04 AM4/3/09
to Rack Development
require 'rack'

class FooRack
def call(env)
content=''
while true
#something check the connection
puts '.'
sleep 1
end
[200,{"Content-Type"=>"text/html"},content]
end
end

Rack::Handler::Mongrel.run(FooRack.new,:Port=>3003)

When client disconnect, but the script still output '.', is there any
way to check the connection?

Thanks
Miao

Eric Wong

unread,
Apr 3, 2009, 4:50:50 PM4/3/09
to rack-...@googlegroups.com

One thing I've thought about proposing was adding "rack.socket" to env
to get the client socket IO object[1]. Then you could run IO.select
with nil timeout on the socket and check for an exception if the client
closes on you.

But currently there's no standard way to do that other than hacking it
into the handler yourself or walking ObjectSpace (yuck).

[1] - My original reason for wanting "rack.socket" was based around something
more evil, but that reason went away and I stopped caring.

--
Eric Wong

Christian Neukirchen

unread,
Apr 4, 2009, 7:48:49 AM4/4/09
to rack-...@googlegroups.com
Eric Wong <normal...@yhbt.net> writes:

> One thing I've thought about proposing was adding "rack.socket" to env
> to get the client socket IO object[1].

Not generally possible (e.g. on CGI?), but it could be a useful
addition for certain servers...

--
Christian Neukirchen <chneuk...@gmail.com> http://chneukirchen.org

Eric Wong

unread,
Apr 4, 2009, 10:45:24 PM4/4/09
to rack-...@googlegroups.com
Christian Neukirchen <chneuk...@gmail.com> wrote:
>
> Eric Wong <normal...@yhbt.net> writes:
>
> > One thing I've thought about proposing was adding "rack.socket" to env
> > to get the client socket IO object[1].
>
> Not generally possible (e.g. on CGI?), but it could be a useful
> addition for certain servers...

CGI could probably just use stdout for that and IO.select for that in
the exceptfds set (not writefds, since it should already be writable).
Maybe "rack.output" would be a better name than "rack.input"...

If we standardize this, we could have could have standard middleware
that does something like this:

def call(env)
watcher = Thread.new(Thread.current, env) do |parent,env|
begin
IO.select(nil, nil, [ env['rack.output'] ])
rescue Errno::EBADF => err # probably other exceptions depending on OS
parent.raise(err)
end
end
@app.call(env)
ensure
watcher.kill if watcher && watcher.alive?
end

(Completely untested)

--
Eric Wong

JiangMiao

unread,
Apr 5, 2009, 2:42:32 AM4/5/09
to Rack Development
On Apr 5, 10:45 am, Eric Wong <normalper...@yhbt.net> wrote:
> Christian Neukirchen <chneukirc...@gmail.com> wrote:
Thank you very much. according the reply I write these codes

require 'rubygems'
require 'rack'

class Rack::Handler::Mongrel
alias_method :default_process, :process

def process(request,response)
if @app.respond_to? :raw_call
return @app.raw_call(request,response)
end
default_process(request,response)
end
end

class FooRack
def raw_call(req,resp)
sid=resp.object_id.to_s
puts "#{sid} begin"
resp.status=200
resp.send_status(nil)
resp.header['Content-Type']='text/plain'
resp.send_header
while true
raise "#{sid} Client disconnected" if IO.select
([resp.socket],nil,nil,0)
resp.write sid+"\n"
sleep 0.1
end
rescue
puts $!.message
ensure
puts "#{sid} end"
end
end

Rack::Handler::Mongrel.run(FooRack.new,:Port=>3003)

use IO.select([resp.socket],nil,nil,0), the problem solved, pass test
on debian 5+ruby 1.8.6+rack 0.9.1
It returns array when the client disconnected, otherwise it returns
nil

Reply all
Reply to author
Forward
0 new messages