|
3 | 3 | import html
|
4 | 4 | import logging
|
5 | 5 | import re
|
| 6 | +from multiprocessing import Process, Queue |
6 | 7 |
|
7 | 8 | import babel
|
8 | 9 | import lxml
|
@@ -544,32 +545,42 @@ def verify_upgraded_jinja_fields(cr):
|
544 | 545 |
|
545 | 546 |
|
546 | 547 | def is_converted_template_valid(env, template_before, template_after, model_name, record_id, engine="inline_template"):
|
547 |
| - render_before = None |
548 |
| - with contextlib.suppress(Exception): |
549 |
| - render_before = _render_template_jinja(env, template_before, model_name, record_id) |
550 |
| - |
551 |
| - render_after = None |
552 |
| - if render_before is not None: |
553 |
| - try: |
554 |
| - with mute_logger("odoo.addons.mail.models.mail_render_mixin"): |
555 |
| - render_after = env["mail.render.mixin"]._render_template( |
556 |
| - template_after, model_name, [record_id], engine=engine |
557 |
| - )[record_id] |
558 |
| - except Exception: |
559 |
| - pass |
560 |
| - |
561 |
| - # post process qweb render to remove comments from the rendered jinja in |
562 |
| - # order to avoid false negative because qweb never render comments. |
563 |
| - if render_before and render_after and engine == "qweb": |
564 |
| - element_before = lxml.html.fragment_fromstring(render_before, create_parent="div") |
565 |
| - for comment_element in element_before.xpath("//comment()"): |
566 |
| - comment_element.getparent().remove(comment_element) |
567 |
| - render_before = lxml.html.tostring(element_before, encoding="unicode") |
568 |
| - render_after = lxml.html.tostring( |
569 |
| - lxml.html.fragment_fromstring(render_after, create_parent="div"), encoding="unicode" |
570 |
| - ) |
| 548 | + def callback(q): |
| 549 | + render_before = None |
| 550 | + with contextlib.suppress(Exception): |
| 551 | + render_before = _render_template_jinja(env, template_before, model_name, record_id) |
| 552 | + |
| 553 | + render_after = None |
| 554 | + if render_before is not None: |
| 555 | + try: |
| 556 | + with mute_logger("odoo.addons.mail.models.mail_render_mixin"): |
| 557 | + render_after = env["mail.render.mixin"]._render_template( |
| 558 | + template_after, model_name, [record_id], engine=engine |
| 559 | + )[record_id] |
| 560 | + except Exception: |
| 561 | + pass |
| 562 | + |
| 563 | + # post process qweb render to remove comments from the rendered jinja in |
| 564 | + # order to avoid false negative because qweb never render comments. |
| 565 | + if render_before and render_after and engine == "qweb": |
| 566 | + element_before = lxml.html.fragment_fromstring(render_before, create_parent="div") |
| 567 | + for comment_element in element_before.xpath("//comment()"): |
| 568 | + comment_element.getparent().remove(comment_element) |
| 569 | + render_before = lxml.html.tostring(element_before, encoding="unicode") |
| 570 | + render_after = lxml.html.tostring( |
| 571 | + lxml.html.fragment_fromstring(render_after, create_parent="div"), encoding="unicode" |
| 572 | + ) |
| 573 | + |
| 574 | + q.put(render_before is not None and render_before == render_after) |
571 | 575 |
|
572 |
| - return render_before is not None and render_before == render_after |
| 576 | + # to avoid memory leaks in external C libraries (lxml/libxml2), process in a forked child |
| 577 | + queue = Queue() |
| 578 | + proc = Process(target=callback, args=[queue]) |
| 579 | + proc.start() |
| 580 | + res = queue.get(timeout=60) |
| 581 | + if proc.is_alive(): |
| 582 | + proc.kill() |
| 583 | + return res |
573 | 584 |
|
574 | 585 |
|
575 | 586 | # jinja render
|
|
0 commit comments