Hello all, I''ve been learning Ruby and playing with a chat server I built using GServer. After into an issue I found with GServer, that no one else seemed to notice (actually, similar to this question, GServer is hard to kill nicely, especially when you want to.), I found references to EventMachine, and rebuilt my server using it. I much prefer EventMachine''s model. The problem I am having is I''d like it to be possible to shutdown the server, for whatever reason. I have a command coded that should tell everyone who is connected that ''So-and-so has executed a shutdown.'', and then loops through the connections and calls close_connection(true) so they''ll see the message before being disconnected. The problem then becomes getting EventMachine to quit, but not until it''s handled the output and disconnected everyone. I''ve tried following with EventMachine::stop and EventMachine::stop_event_loop, both of which work at stopping the machine, but do not output the last writes to users. Some way to tell that there''s no one connected or no more pending traffic or the like would be great. I finally set up a flag to stop allowing incoming connections, and after the code to close existing connections, used EM#add_timer to kill the server. That worked, but isn''t necessarily scalable. Two seconds may be long enough now, but later I may need 5, or 10, if there are a lot of connections. I''d much rather trigger it off the actual event I''m interested in, being a lack of pending outgoing data. The eventual hope is to use EM/Ruby as an LPC style MUD driver. I can already accomplish live updates of the running code due to Ruby''s flexibility; I put the ''protocol'' module and the class that has all the commands and user-interaction stuff in a separate file from the code that actually instantiates it, and then made a refresh command that causes the server to re-load that file. If I decide to go much further than this with it, there''s a lot of room for further breaking it down by file. Thanks, Dave Skidmore -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071107/8114cf1a/attachment-0001.html
> > > I''ve tried following with EventMachine::stop and > EventMachine::stop_event_loop, both of which work at stopping the machine, > but do not output the last writes to users. Some way to tell that > there''s > no one connected or no more pending traffic or the like would be great. I > finally set up a flag to stop allowing incoming connections, and after the > code to close existing connections, used EM#add_timer to kill the server. > That worked, but isn''t necessarily scalable. Two seconds may be long > enough > now, but later I may need 5, or 10, if there are a lot of > connections. I''d > much rather trigger it off the actual event I''m interested in, being a > lack > of pending outgoing data.Make a count of outstanding connections, decrement it on unbind (for each connection call write_data, then close_connection_after_writing, then decrement your counter on ''unbind'' -- the last one should call EM::close. Anyway some coordinator between clients. I haven''t ever actually done what I described, but it might work. I guess this means that a function ''total outstanding connections count'' might be nice, too. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071107/d121044c/attachment.html
On 11/7/07, Roger Pack <rogerpack2005 at gmail.com> wrote:> > > > I''ve tried following with EventMachine::stop and > > EventMachine::stop_event_loop, both of which work at stopping the > > machine, > > but do not output the last writes to users. Some way to tell that > > there''s > > no one connected or no more pending traffic or the like would be > > great. I > > finally set up a flag to stop allowing incoming connections, and after > > the > > code to close existing connections, used EM#add_timer to kill the > > server. > > That worked, but isn''t necessarily scalable. Two seconds may be long > > enough > > now, but later I may need 5, or 10, if there are a lot of > > connections. I''d > > much rather trigger it off the actual event I''m interested in, being a > > lack > > of pending outgoing data. > > > Make a count of outstanding connections, decrement it on unbind (for each > connection call write_data, then close_connection_after_writing, then > decrement your counter on > ''unbind'' -- the last one should call EM::close. Anyway some coordinator between clients. I haven''t ever actually done what I described, but it might work. > > > I guess this means that a function ''total outstanding connections count'' > might be nice, too. >I have an object I use that keeps track of all the connections. They get added in the EM::start_server block, and removed in the unbind call. That''s a good idea, though, I''ll give it a shot. Dave Skidmore -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071107/ad86f26f/attachment.html
On 11/7/07, Dave Skidmore <dave.skidmore at gmail.com> wrote:> > On 11/7/07, Roger Pack <rogerpack2005 at gmail.com> wrote: > > > > > > > I''ve tried following with EventMachine::stop and > > > EventMachine::stop_event_loop, both of which work at stopping the > > > machine, > > > but do not output the last writes to users. Some way to tell that > > > there''s > > > no one connected or no more pending traffic or the like would be > > > great. I > > > finally set up a flag to stop allowing incoming connections, and after > > > the > > > code to close existing connections, used EM#add_timer to kill the > > > server. > > > That worked, but isn''t necessarily scalable. Two seconds may be long > > > enough > > > now, but later I may need 5, or 10, if there are a lot of > > > connections. I''d > > > much rather trigger it off the actual event I''m interested in, being a > > > lack > > > of pending outgoing data. > > > > > > Make a count of outstanding connections, decrement it on unbind (for > > each connection call write_data, then close_connection_after_writing, then > > decrement your counter on > > ''unbind'' -- the last one should call EM::close. Anyway some coordinator between clients. I haven''t ever actually done what I described, but it might work. > > > > > > I guess this means that a function ''total outstanding connections count'' > > might be nice, too. > > > > I have an object I use that keeps track of all the connections. They get > added in the EM::start_server block, and removed in the unbind call. That''s > a good idea, though, I''ll give it a shot. > > Dave Skidmore > > >FYI that works, thanks Roger! I added code to the removeUser method to do a check to see if the user list is empty, and then to see if there is a valid Proc object set. If so, it calls the Proc object. The Proc reference is an instance var that gets set by the shutdown command, so the server can sit empty unless someone is shutting it down. Now I need to beef up the user/connection object with some security, and persistance. Dave Skidmore -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071107/f40aa819/attachment.html
Francis Cianfrocca
2007-Nov-07 12:47 UTC
[Eventmachine-talk] Gracefully stopping EventMachine?
On Nov 7, 2007 3:05 PM, Dave Skidmore <dave.skidmore at gmail.com> wrote:> Hello all, > > I''ve been learning Ruby and playing with a chat server I built using > GServer. After into an issue I found with GServer, that no one else seemed > to notice (actually, similar to this question, GServer is hard to kill > nicely, especially when you want to.), I found references to EventMachine, > and rebuilt my server using it. I much prefer EventMachine''s model. > > The problem I am having is I''d like it to be possible to shutdown the > server, for whatever reason. I have a command coded that should tell > everyone who is connected that ''So-and-so has executed a shutdown.'', and > then loops through the connections and calls close_connection(true) so > they''ll see the message before being disconnected. The problem then becomes > getting EventMachine to quit, but not until it''s handled the output and > disconnected everyone. > > I''ve tried following with EventMachine::stop and > EventMachine::stop_event_loop, both of which work at stopping the machine, > but do not output the last writes to users. Some way to tell that there''s > no one connected or no more pending traffic or the like would be great. I > finally set up a flag to stop allowing incoming connections, and after the > code to close existing connections, used EM#add_timer to kill the server. > That worked, but isn''t necessarily scalable. Two seconds may be long enough > now, but later I may need 5, or 10, if there are a lot of connections. I''d > much rather trigger it off the actual event I''m interested in, being a lack > of pending outgoing data.I know there''s a way to stop a listening TCP server. I remember Kirk had me put that in a while ago. That would be more graceful than setting a flag and having the accept-handler just close incoming connections. I''m trying to come up with a neat way to stop the reactor after all the connections in a set have executed unbind. All I can think of is to decrement a class variable in your protocol handler, and call EM#stop when it goes to zero. And of course you need a way to make sure that mechanism doesn''t trigger until you want it to. Otherwise whenever you get one connection and then none on a quiet run, your server will stop!