Currently I have this to fix it. The question is: Is the infrequent
occurrance of a blocked socket write while snooping frequent enough to
complicate the code to fix? See the diff for more details on the effect I
am speaking of.
diff -u -p -r1.63 comm.c
--- comm.c 1999/01/08 08:17:01 1.63
+++ comm.c 1999/01/16 05:20:56
@@ -724,10 +724,17 @@ void game_loop(int mother_desc)
next_d = d->next;
if (*(d->output) && FD_ISSET(d->descriptor, &output_set)) {
/* Output for this player is ready */
- if (process_output(d) < 0)
+ switch (process_output(d)) {
+ case -1: /* fatal/unknown error */
close_socket(d);
- else
+ break;
+ case 0: /* write blocked */
+ d->has_prompt = 0;
+ break;
+ default: /* normal */
d->has_prompt = 1;
+ break;
+ }
}
}
@@ -1292,7 +1299,7 @@ int new_descriptor(int s)
int process_output(struct descriptor_data *t)
{
char i[MAX_SOCK_BUF];
- int result;
+ int written, offset = 2;
/* we may need this \r\n for later -- see below */
strcpy(i, "\r\n");
@@ -1316,9 +1323,9 @@ int process_output(struct descriptor_dat
* CRLF, otherwise send the straight output sans CRLF.
*/
if (t->has_prompt) /* && !t->connected) */
- result = write_to_descriptor(t->descriptor, i);
- else
- result = write_to_descriptor(t->descriptor, i + 2);
+ offset = 0;
+
+ written = write_to_descriptor(t->descriptor, i + offset);
/* handle snooping: prepend "% " and send to snooper */
if (t->snoop_by) {
@@ -1341,7 +1348,20 @@ int process_output(struct descriptor_dat
t->bufptr = 0;
*(t->output) = '\0';
- return (result);
+ /*
+ * We blocked, restore the unwritten output. Known
+ * bug in that the snooping immortal will see it twice
+ * but details...
+ */
+ if (written < 0) {
+ write_to_output(i + -written + offset, t);
+ return (0);
+ }
+
+ if (written == 0) /* Error, kill'em. */
+ return (-1);
+
+ return (1);
}
@@ -1450,38 +1470,39 @@ ssize_t perform_socket_write(socket_t de
* encountered.
*
* Returns:
- * 0 If all is well and good,
- * -1 If an error was encountered, so that the player should be cut off
+ * >0 How many bytes written, all is well and good.
+ * 0 If an error was encountered, so that the player should be cut off.
+ * <0 The socket write would block, but wrote this many bytes previously.
*/
int write_to_descriptor(socket_t desc, const char *txt)
{
- size_t total;
- ssize_t bytes_written;
-
- total = strlen(txt);
+ ssize_t bytes_written, bytes_total = 0;
+ size_t total = strlen(txt);
while (total > 0) {
bytes_written = perform_socket_write(desc, txt, total);
if (bytes_written < 0) {
/* Fatal error. Disconnect the player. */
- perror("SYSERR: Write to socket");
- return (-1);
+ perror("SYSERR: write_to_descriptor");
+ return (0);
} else if (bytes_written == 0) {
/*
* Temporary failure -- socket buffer full. For now we'll just
* cut off the player, but eventually we'll stuff the unsent
* text into a buffer and retry the write later. JE 30 June 98.
+ * Implemented the anti-cut-off code he wanted. GG 13 Jan 99.
*/
- log("WARNING: write_to_descriptor: socket write would block, about to close");
- return (-1);
+ log("WARNING: write_to_descriptor: socket write would block.");
+ return (-bytes_total);
} else {
txt += bytes_written;
total -= bytes_written;
+ bytes_total += bytes_written;
}
}
- return (0);
+ return (bytes_total);
}
Thoughts?
--
George Greer
greerga@circlemud.org
http://www.van.ml.org/CircleMUD/
+------------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
| http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
+------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/15/00 PST