shithub: choc

Download patch

ref: f28d798073e571cb3114208cfa81653b9b502f6c
parent: d6556ee4b4d9d2c4c9ac48f998bd387f5416b75d
author: Simon Howard <fraggle@soulsphere.org>
date: Wed Jun 3 16:20:37 EDT 2015

Fix demo desyncs caused by P_RunThinkers() change.

1bcff874c52a changed the behavior of P_RunThinkers() to avoid
dereferencing thinker pointers after they had been freed, but the
modified version of the function was not logically equivalent to
Vanilla version, because the 'next' pointer can be changed by the
thinker function if one is invoked.

This fixes a desync in tnt-speed-movie-0443131.lmp. Thanks to Zvonimir
Bužanić for the bug report and Fabian Greffrath for reporting.

Fixes #547.

--- a/src/doom/p_tick.c
+++ b/src/doom/p_tick.c
@@ -98,11 +98,10 @@
     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
-        nextthinker = currentthinker->next;
-
 	if ( currentthinker->function.acv == (actionf_v)(-1) )
 	{
 	    // time to remove it
+            nextthinker = currentthinker->next;
 	    currentthinker->next->prev = currentthinker->prev;
 	    currentthinker->prev->next = currentthinker->next;
 	    Z_Free(currentthinker);
@@ -111,6 +110,7 @@
 	{
 	    if (currentthinker->function.acp1)
 		currentthinker->function.acp1 (currentthinker);
+            nextthinker = currentthinker->next;
 	}
 	currentthinker = nextthinker;
     }
--- a/src/heretic/p_tick.c
+++ b/src/heretic/p_tick.c
@@ -115,10 +115,9 @@
     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
-        nextthinker = currentthinker->next;
-
         if (currentthinker->function == (think_t) - 1)
         {                       // time to remove it
+            nextthinker = currentthinker->next;
             currentthinker->next->prev = currentthinker->prev;
             currentthinker->prev->next = currentthinker->next;
             Z_Free(currentthinker);
@@ -127,6 +126,7 @@
         {
             if (currentthinker->function)
                 currentthinker->function(currentthinker);
+            nextthinker = currentthinker->next;
         }
         currentthinker = nextthinker;
     }
--- a/src/hexen/p_tick.c
+++ b/src/hexen/p_tick.c
@@ -91,17 +91,18 @@
     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
-        nextthinker = currentthinker->next;
-
         if (currentthinker->function == (think_t) - 1)
         {                       // Time to remove it
+            nextthinker = currentthinker->next;
             currentthinker->next->prev = currentthinker->prev;
             currentthinker->prev->next = currentthinker->next;
             Z_Free(currentthinker);
         }
-        else if (currentthinker->function)
+        else
         {
-            currentthinker->function(currentthinker);
+            if (currentthinker->function)
+                currentthinker->function(currentthinker);
+            nextthinker = currentthinker->next;
         }
 
         currentthinker = nextthinker;
--- a/src/strife/p_tick.c
+++ b/src/strife/p_tick.c
@@ -104,11 +104,10 @@
     currentthinker = thinkercap.next;
     while (currentthinker != &thinkercap)
     {
-        nextthinker = currentthinker->next;
-
         if ( currentthinker->function.acv == (actionf_v)(-1) )
         {
             // time to remove it
+            nextthinker = currentthinker->next;
             currentthinker->next->prev = currentthinker->prev;
             currentthinker->prev->next = currentthinker->next;
             Z_Free (currentthinker);
@@ -117,6 +116,7 @@
         {
             if (currentthinker->function.acp1)
                 currentthinker->function.acp1 (currentthinker);
+            nextthinker = currentthinker->next;
         }
 
         currentthinker = nextthinker;