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