From b298347fdcaee0d44b7b0b39f9764fba4cf7415c Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Date: Wed, 7 Aug 2024 03:28:12 +0200 Subject: Stop the layouting loop after 1000 iterations Prevents Dillo from hoarding the CPU due to an infinite loop in the layouting. We also return the control to FLTK to update the screen and process events each 100 iterations, to keep the window responsive. It doesn't fix the root cause of the github-infinite-loop test, but it does allow the rendering to finish with no differences with the reference test. --- dw/layout.cc | 28 +++++++++++++++++++++++----- dw/layout.hh | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'dw') diff --git a/dw/layout.cc b/dw/layout.cc index 96653643..ee54e892 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -307,7 +307,7 @@ Layout::Layout (Platform *platform) layoutImgRenderer = NULL; resizeIdleCounter = queueResizeCounter = sizeAllocateCounter - = sizeRequestCounter = getExtremesCounter = 0; + = sizeRequestCounter = getExtremesCounter = resizeCounter = 0; } Layout::~Layout () @@ -443,6 +443,10 @@ void Layout::setWidget (Widget *widget) addWidget (widget); updateCursor (); + + /* Reset the resizeCounter when we change the top level widget, as we are + * changing to another page */ + resizeCounter = 0; } /** @@ -868,16 +872,30 @@ void Layout::resizeIdle () enterResizeIdle (); - //static int calls = 0; - // There are two commits, 2863:b749629fbfc9 and 4645:ab70f9ce4353, the second // reverting the former. Interrestingly, the second fixes a bug. However, it // should still examined what happens here, and what happens the other calls // to Layout::resizeIdle() which should be still in the queue. (See // Layout::queueResize(), where resizeIdleId is indeed checked.) - while (resizeIdleId != -1) { - _MSG("Layout::resizeIdle calls = %d\n", ++calls); + for (int i = 0; resizeIdleId != -1; i++) { + + /* Prevent infinite resize loop, if we reach this point it is very likely + * there is a bug in the layouting process */ + if (resizeCounter >= 1000) { + MSG_ERR("Emergency layout stop after %d iterations\n", resizeCounter); + MSG_ERR("Please file a bug report with the complete console output\n"); + resizeIdleId = -1; + break; + } + + /* Only allow 100 iterations before returning to redraw the screen. */ + if (i >= 100) { + MSG_WARN("Stopping layout loop after %d iterations\n", resizeCounter); + break; + } + + resizeCounter++; for (typed::Iterator it = queueResizeList->iterator(); it.hasNext (); ) { diff --git a/dw/layout.hh b/dw/layout.hh index aada2069..e2b64901 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -246,7 +246,7 @@ private: ...Entered) defined here and in Widget. */ int resizeIdleCounter, queueResizeCounter, sizeAllocateCounter, - sizeRequestCounter, getExtremesCounter; + sizeRequestCounter, getExtremesCounter, resizeCounter; void enterResizeIdle () { resizeIdleCounter++; } void leaveResizeIdle () { resizeIdleCounter--; } -- cgit v1.2.3