master/master.c
branchstable-1.5
changeset 2085 23ffec5c9c5b
parent 2082 775d1a02f204
child 2109 755e6ce823f0
--- a/master/master.c	Fri Jul 08 14:28:07 2011 +0200
+++ b/master/master.c	Thu Jul 21 18:25:38 2011 +0200
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  $Id: master.c,v b5391b329b5d 2010/11/30 14:24:21 fp $
+ *  $Id$
  *
  *  Copyright (C) 2006-2008  Florian Pose, Ingenieurgemeinschaft IgH
  *
@@ -821,6 +821,8 @@
         ec_datagram_t *datagram /**< datagram */
         )
 {
+    ec_datagram_t *queued_datagram;
+
     switch (datagram->state) {
         case EC_DATAGRAM_QUEUED:
             datagram->skip_count++;
@@ -835,10 +837,27 @@
             break;
 
         default:
-            list_add_tail(&datagram->queue, &master->datagram_queue);
+            break;
+    }
+
+    /* It is possible, that a datagram in the queue is re-initialized with the
+     * ec_datagram_<type>() methods and then shall be queued with this method.
+     * In that case, the state is already reset to EC_DATAGRAM_INIT. Check if
+     * the datagram is queued to avoid duplicate queuing (which results in an
+     * infinite loop!). Set the state to EC_DATAGRAM_QUEUED again, probably
+     * causing an unmatched datagram. */
+    list_for_each_entry(queued_datagram, &master->datagram_queue, queue) {
+        if (queued_datagram == datagram) {
+            datagram->skip_count++;
+            EC_MASTER_DBG(master, 1, "Skipping re-initialized datagram %p.\n",
+                    datagram);
             datagram->state = EC_DATAGRAM_QUEUED;
-            break;
-    }
+            return;
+        }
+    }
+
+    list_add_tail(&datagram->queue, &master->datagram_queue);
+    datagram->state = EC_DATAGRAM_QUEUED;
 }
 
 /*****************************************************************************/