WeasyPrint: Infinite loop in multi-column layout after first (page-)break-before

Using WeasyPrint==51, in a 2-column layout, write_pdf() causes an infinite loop when (page-)break-before: always; is applied to more than 1 block:

<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
      .content {
        columns: 2;
      }

      .page-break {
        break-before: always;
      }
    </style>
  </head>

  <body>
    <div class="content">
      <div>Page 1, column 1</div>
      <div class="page-break">Page 1, column 2</div>
      <div class="page-break">Page 2, column 1</div>
    </div>
  </body>
</html>

The same error happens for versions 48, 49 and 50. WeasyPrint==47 works fine. Leaving the second page-break block away, the pdf renders.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 21 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@liZe @aschmitz Thanks for this fix!

Yep, the reproducer at the top of this issue is indeed an infinite loop. You end up looping in here:

https://github.com/Kozea/WeasyPrint/blob/e17e5368f74ea95be1c83b69fc0af99210a30470/weasyprint/layout/column.py#L149-L162

Effectively, this loop is trying to increase the height of the columns until everything fits between the two columns. It’s failing because it will never fit all three required columns into two columns.

An easy resolution would be to pop an additional condition in line 209 and 212:

https://github.com/Kozea/WeasyPrint/blob/e17e5368f74ea95be1c83b69fc0af99210a30470/weasyprint/layout/column.py#L209-L213

We could add or next_page['break'] != 'any' to the condition and escape this loop (because next_page has break set to page (or some other page specifier) rather than any when it must break), but it’s not clear that doing so is really correct. In particular, if you were to double the “Page 1, column 1” div, you’d end up with one copy on each of the first two columns, then the forced break would go onto the next column (page 2, column 1).

I’d have to think for a while on what a good way to resolve that is: perhaps there’s some way to make a last-ditch attempt to heighten the remaining columns if we’d have to break pages? @liZe may (hopefully will!) have better ideas.

Because that loop is in the column code, though, I don’t think it’s the cause of the issue you’re running into, @drboone. Is there any chance you can try deleting chunks of your HTML + CSS until it works, and then re-add whatever was last to get it to a more minimal (and ideally, sharable) state? I’m not a maintainer, but I’ve been digging into some performance issues we’ve been running into at work and might be able to help triage things.

I was curious, so I left this running. After 12 hours of 100% cpu use, it still hasn’t finished, but is using nearly 9.5 GB of RAM.

But I’m pretty sure that solving this particular halting problem is less relevant than the fact that it’s completely impractical if it takes even multiple minutes to render. 😃

Are people actually seeing the comments on this issue?