<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40605 >

> [cazf...@gmail.com - Fri Dec 19 11:08:09 2008]:
> 
>  2.1.8, using fantasy ruleset
> 
> Program terminated with signal 11, Segmentation fault.
> [New process 20595]
> #0  0x000000000042a01b in genlist_size ()
> (gdb) bt full
> #0  0x000000000042a01b in genlist_size ()
> No locals.
> #1  0x00000000004e6e40 in timer_list_size ()
> No locals.
> #2  0x00000000004e6d8d in close_connection ()
> No locals.
> [...]
> 
>  This is probably related to the fact that incoming connection was
> rejected by auth code.
> 
> 
>  I'm not sure if this is bug in official Freeciv. I have local
> modification for prohibiting login with certain accounts, and bug
> might be in that modification.

I have seen a very similar backtrace in the past; this
is probably due to an attempted used of a NULL genlist.
The attached patches for S2_1 and trunk add checks for
the NULL list and should at least prevent crashing.


-----------------------------------------------------------------------
ピンポン!
diff --git a/server/sernet.c b/server/sernet.c
index 81d6493..b7ab4a5 100644
--- a/server/sernet.c
+++ b/server/sernet.c
@@ -116,6 +116,9 @@ static int socklan;
 #define SPECLIST_TAG timer
 #define SPECLIST_TYPE struct timer
 #include "speclist.h"
+#define timer_list_iterate(ARG_list, NAME_item) \
+  TYPED_LIST_ITERATE(struct timer, (ARG_list), NAME_item)
+#define timer_list_iterate_end LIST_ITERATE_END
 
 #define PROCESSING_TIME_STATISTICS 0
 
@@ -196,14 +199,18 @@ static void handle_readline_input_callback(char *line)
 *****************************************************************************/
 void close_connection(struct connection *pconn)
 {
-  while (timer_list_size(pconn->server.ping_timers) > 0) {
-    struct timer *timer = timer_list_get(pconn->server.ping_timers, 0);
+  if (!pconn) {
+    return;
+  }
 
-    timer_list_unlink(pconn->server.ping_timers, timer);
-    free_timer(timer);
+  if (pconn->server.ping_timers != NULL) {
+    timer_list_iterate(pconn->server.ping_timers, timer) {
+      free_timer(timer);
+    } timer_list_iterate_end;
+    timer_list_unlink_all(pconn->server.ping_timers);
+    timer_list_free(pconn->server.ping_timers);
+    pconn->server.ping_timers = NULL;
   }
-  assert(timer_list_size(pconn->server.ping_timers) == 0);
-  timer_list_free(pconn->server.ping_timers);
 
   /* safe to do these even if not in lists: */
   conn_list_unlink(game.all_connections, pconn);
diff --git a/utility/timing.c b/utility/timing.c
index 49337c8..ee2a6a1 100644
--- a/utility/timing.c
+++ b/utility/timing.c
@@ -213,7 +213,9 @@ struct timer *renew_timer_start(struct timer *t, enum timer_timetype type,
 ***********************************************************************/
 void free_timer(struct timer *t)
 {
-  free(t);
+  if (t != NULL) {
+    free(t);
+  }
 }
 
 /********************************************************************** 
diff --git a/server/sernet.c b/server/sernet.c
index 055bff1..7f1a130 100644
--- a/server/sernet.c
+++ b/server/sernet.c
@@ -118,6 +118,9 @@ static int socklan;
 #define SPECLIST_TAG timer
 #define SPECLIST_TYPE struct timer
 #include "speclist.h"
+#define timer_list_iterate(ARG_list, NAME_item) \
+  TYPED_LIST_ITERATE(struct timer, (ARG_list), NAME_item)
+#define timer_list_iterate_end LIST_ITERATE_END
 
 #define PROCESSING_TIME_STATISTICS 0
 
@@ -198,16 +201,19 @@ static void handle_readline_input_callback(char *line)
 *****************************************************************************/
 void close_connection(struct connection *pconn)
 {
-  cancel_connection_votes(pconn);
+  if (!pconn) {
+    return;
+  }
 
-  while (timer_list_size(pconn->server.ping_timers) > 0) {
-    struct timer *timer = timer_list_get(pconn->server.ping_timers, 0);
+  cancel_connection_votes(pconn);
 
-    timer_list_unlink(pconn->server.ping_timers, timer);
-    free_timer(timer);
+  if (pconn->server.ping_timers != NULL) {
+    timer_list_iterate(pconn->server.ping_timers, timer) {
+      free_timer(timer);
+    } timer_list_iterate_end;
+    timer_list_free(pconn->server.ping_timers);
+    pconn->server.ping_timers = NULL;
   }
-  assert(timer_list_size(pconn->server.ping_timers) == 0);
-  timer_list_free(pconn->server.ping_timers);
 
   /* safe to do these even if not in lists: */
   conn_list_unlink(game.all_connections, pconn);
diff --git a/utility/timing.c b/utility/timing.c
index 31ad317..66ac3d0 100644
--- a/utility/timing.c
+++ b/utility/timing.c
@@ -213,7 +213,9 @@ struct timer *renew_timer_start(struct timer *t, enum timer_timetype type,
 ***********************************************************************/
 void free_timer(struct timer *t)
 {
-  free(t);
+  if (t != NULL) {
+    free(t);
+  }
 }
 
 /********************************************************************** 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to