diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/client/clinet.c codeciv/client/clinet.c --- freeciv/client/clinet.c Sat Jul 21 13:48:47 2001 +++ codeciv/client/clinet.c Sat Jul 21 14:35:57 2001 @@ -155,6 +155,7 @@ aconnection.last_write = 0; aconnection.used = 1; + aconnection.delayed_disconnect = 0; /* gui-dependent details now in gui_main.c: */ add_net_input(aconnection.sock); diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/common/connection.c codeciv/common/connection.c --- freeciv/common/connection.c Sat Jul 21 13:49:05 2001 +++ codeciv/common/connection.c Sat Jul 21 15:07:22 2001 @@ -54,6 +54,12 @@ * blank/unknown/not-applicable address: */ const char blank_addr_str[] = "---.---.---.---"; + +/* This is only used by the server. + If it is set the disconnection of conns is posponed. This is sometimes + neccesary as removing a random connection while we are iterating through + a connection list might corrupt the list. */ +int delayed_disconnect = 0; /************************************************************************** Command access levels for client-side use; at present, they are only @@ -147,7 +153,6 @@ return -1; } - /************************************************************************** write wrapper function -vasc **************************************************************************/ @@ -156,6 +161,17 @@ { int start, nput, nblock; + if (pc->delayed_disconnect) { + if (delayed_disconnect) { + return 0; + } else { + if (close_callback) { + (*close_callback)(pc); + } + return -1; + } + } + for (start=0; buf->ndata-start>limit;) { fd_set writefs, exceptfs; struct timeval tv; @@ -172,10 +188,15 @@ } if (FD_ISSET(pc->sock, &exceptfs)) { - if (close_callback) { - (*close_callback)(pc); + if (delayed_disconnect) { + pc->delayed_disconnect = 1; + return 0; + } else { + if (close_callback) { + (*close_callback)(pc); + } + return -1; } - return -1; } if (FD_ISSET(pc->sock, &writefs)) { @@ -187,10 +208,15 @@ break; } #endif - if (close_callback) { - (*close_callback)(pc); + if (delayed_disconnect) { + pc->delayed_disconnect = 1; + return 0; + } else { + if (close_callback) { + (*close_callback)(pc); + } + return -1; } - return -1; } start += nput; } @@ -231,6 +257,13 @@ static int add_connection_data(struct connection *pc, unsigned char *data, int len) { + if (pc && !delayed_disconnect && pc->delayed_disconnect) { + if (close_callback) { + (*close_callback)(pc); + } + return 0; + } + if (pc && pc->used) { struct socket_packet_buffer *buf; @@ -242,16 +275,26 @@ /* added this check so we don't gobble up too much mem */ if (buf->nsize > MAX_LEN_BUFFER) { - if (close_callback) { - (*close_callback)(pc); - } - return 0; - } else { - if (!(buf->data = fc_realloc(buf->data, buf->nsize))) { + if (delayed_disconnect) { + pc->delayed_disconnect = 1; + return 1; + } else { if (close_callback) { (*close_callback)(pc); } return 0; + } + } else { + if (!(buf->data = fc_realloc(buf->data, buf->nsize))) { + if (delayed_disconnect) { + pc->delayed_disconnect = 1; + return 1; + } else { + if (close_callback) { + (*close_callback)(pc); + } + return 0; + } } } } diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/common/connection.h codeciv/common/connection.h --- freeciv/common/connection.h Sat Jul 21 13:49:05 2001 +++ codeciv/common/connection.h Sat Jul 21 15:51:18 2001 @@ -111,6 +111,10 @@ int route_length; /* These are used when recieving goto routes; they are send split, and in the time where the route is partially recieved it is stored here. */ + + int delayed_disconnect; + /* Something has occured that means the connection should be closed, but + the closing has been postponed. */ }; @@ -143,5 +147,7 @@ const char *conn_description(const struct connection *pconn); extern const char blank_addr_str[]; - + +extern int delayed_disconnect; + #endif /* FC__CONNECTION_H */ diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/sernet.c codeciv/server/sernet.c --- freeciv/server/sernet.c Sat Jul 21 13:49:15 2001 +++ codeciv/server/sernet.c Sat Jul 21 14:17:17 2001 @@ -622,6 +622,7 @@ pconn->byte_swap = 0; pconn->capability[0] = '\0'; pconn->access_level = access_level_for_next_connection(); + pconn->delayed_disconnect = 0; sz_strlcpy(pconn->name, makeup_connection_name(&pconn->id)); sz_strlcpy(pconn->addr, diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/srv_main.c codeciv/server/srv_main.c --- freeciv/server/srv_main.c Sat Jul 21 13:49:15 2001 +++ codeciv/server/srv_main.c Sat Jul 21 15:06:16 2001 @@ -1393,13 +1393,15 @@ * Safe to unlink even if not in list: */ conn_list_unlink(&game.est_connections, pconn); + delayed_disconnect++; notify_conn(&game.est_connections, _("Game: Lost connection: %s."), desc); - + if (pplayer == NULL) { /* This happens eg if the player has not yet joined properly. */ + delayed_disconnect--; return; } - + unassociate_player_connection(pplayer, pconn); /* Remove from lists so this conn is not included in broadcasts. @@ -1439,6 +1441,7 @@ } check_for_full_turn_done(); } + delayed_disconnect--; } /**************************************************************************