Is there a way to make the quit command wait until everything is sent before it completely logs the player out? I have several messages and whatnot I'd like players to receive on exiting the game, however, hardly any of it gets entirely through before the game kills the connection like so:
Everything begins to fade black .. and then … nothing.
A strange voice says, 'See you again, Banner .. real soon..'
Date Modified: Mon Nov 19 23:51:41 2007 Modified By: Banner ——————————————————————————–
Random Qu
^^ cuts off above with about 3 more lines to send
02 Jun, 2009, David Haley wrote in the 2nd comment:
Votes: 0
Well, sure. Just make sure to send all data in a connection's output buffer before actually closing the connection. I thought this was a default feature of the networking code?
Well, sure. Just make sure to send all data in a connection's output buffer before actually closing the connection. I thought this was a default feature of the networking code?
The call to close the connection is after all the printfs if that is what you mean.
The call to close the connection is after all the printfs if that is what you mean.
The close call should occur after the output loop does it's send/write. One way to do that is instead of closing the socket in quit, you mark the descriptor with a flag indicating it should be closed. The add a loop after the output loop the process all the descriptors and close those with the close flag on.
02 Jun, 2009, David Haley wrote in the 7th comment:
Votes: 0
Well, you don't want to force a total flush as that can hang the MUD while flushing the buffer. What you really want to do is to keep processing the socket in the normal way until the output buffer is empty, disallowing all input, and then disconnect the socket. It might help to have some kind of timeout (5min? … whatever) in case it doesn't flush in some reasonable delay.
In your do_quit function, can't you just print what you need before doing all the disconnecting stuff?
Banner said:
David Haley said:
Well, sure. Just make sure to send all data in a connection's output buffer before actually closing the connection. I thought this was a default feature of the networking code?
The call to close the connection is after all the printfs if that is what you mean.
02 Jun, 2009, David Haley wrote in the 10th comment:
Votes: 0
You don't want to actually close the connection after sending to it – that will immediately close it, even if the buffer has not been sent yet. When you call send_to_char or ch_printf it doesn't immediately send the bytes down the socket, it sticks them onto the output buffer and only later are they actually sent.
You don't want to actually close the connection after sending to it – that will immediately close it, even if the buffer has not been sent yet. When you call send_to_char or ch_printf it doesn't immediately send the bytes down the socket, it sticks them onto the output buffer and only later are they actually sent.
How would you allow it to process the buffer first, or introduce a timeout? Precisely what functions would I need?
02 Jun, 2009, David Haley wrote in the 12th comment:
Votes: 0
You would need some kind of marker on the socket object to note that it is in the process of being closed. The normal output routine already takes care of sending output when possible. You would need to have it close sockets with no pending I/O, and with the closing marker. As for a timeout, you can have some kind of last-activity time stamp.
As I said, I thought all of this was already standard in FUSS for example, so you might want to look there before working on this too much.
Though just marking the connection for deletion, and having the normal game loop finish sending output is probably a better design for how to do the quit, I think the problem here stems from how SMAUG handles flush_buffer() when there is a lot of data to send. Close_socket() does call flush_buffer(), but if there is more then so much data to send (4k in stock), it will send just part of it (.5k in stock). In the normal quit, you don't send enough data for this to be a problem, but you are sending quite a lot more and are probably going over the limit to trigger sending only part of the output, causing the rest to not ever be sent as the connection closes. You could just change the limits in flush_buffer(), or have it detect if this is a closing connection and send all data (like it does now if the mud is going down). You could do the later by setting a flag on the descriptor, passing a new bool argument to flush_buffer(), or even using the quitting_char global. But I would look at flush_buffer() and up the numbers there to at least see if that is the root problem, even if you do a different final fix.
03 Jun, 2009, David Haley wrote in the 14th comment:
Votes: 0
You probably don't want to hang the MUD while trying to flush the buffer on a quitting connection. If you don't leave the function, until the buffer is flushed, your MUD will keep trying to send until all data is sent. That's why it doesn't force the sending of the entire buffer (although it shouldn't just discard the rest).