Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. PySide6 6.11.1: QWebEngineUrlRequestJob.requestBody() causes SIGSEGV for POST requests to custom URL schemes
Qt 6.11 is out! See what's new in the release blog

PySide6 6.11.1: QWebEngineUrlRequestJob.requestBody() causes SIGSEGV for POST requests to custom URL schemes

Scheduled Pinned Locked Moved Unsolved Qt for Python
2 Posts 1 Posters 31 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    PyXiion
    wrote last edited by
    #1

    PySide6 QWebEngineUrlRequestJob.requestBody() causes SIGSEGV on POST requests to custom URL schemes

    The crash happens immediately inside requestBody(), before accessing the returned object.

    MRE

    from __future__ import annotations
    
    import sys
    
    from PySide6 import __version__ as pyside6_ver
    from PySide6.QtCore import QByteArray, QBuffer, QIODevice, QTimer, QUrl, qVersion
    from PySide6.QtWebEngineCore import (
        QWebEngineUrlScheme,
        QWebEngineUrlSchemeHandler,
        QWebEngineUrlRequestJob,
        QWebEngineProfile,
    )
    
    print(f"Python: {sys.version}", flush=True)
    print(f"PySide6: {pyside6_ver}", flush=True)
    print(f"Qt: {qVersion()}", flush=True)
    
    scheme = QWebEngineUrlScheme(b"mre")
    scheme.setFlags(
        QWebEngineUrlScheme.Flag.SecureScheme
        | QWebEngineUrlScheme.Flag.ContentSecurityPolicyIgnored
        | QWebEngineUrlScheme.Flag.FetchApiAllowed
        | QWebEngineUrlScheme.Flag.CorsEnabled
    )
    scheme.setSyntax(QWebEngineUrlScheme.Syntax.Host)
    QWebEngineUrlScheme.registerScheme(scheme)
    
    from PySide6.QtWidgets import QApplication
    from PySide6.QtWebEngineWidgets import QWebEngineView
    
    
    class Handler(QWebEngineUrlSchemeHandler):
        def requestStarted(self, job: QWebEngineUrlRequestJob) -> None:
            print(
                f"{job.requestMethod().data().decode()} {job.requestUrl().toString()}"
            )
    
            print("before requestBody()", flush=True)
            job.requestBody()
            print("after requestBody()", flush=True)
    
            buf = QBuffer()
            buf.setData(b'{"ok":true}')
            buf.open(QIODevice.OpenModeFlag.ReadOnly)
            buf.setParent(job)
            job.reply(b"application/json", buf)
    
    
    app = QApplication(sys.argv)
    
    handler = Handler()
    QWebEngineProfile.defaultProfile().installUrlSchemeHandler(
        QByteArray(b"mre"), handler
    )
    
    view = QWebEngineView()
    view.setHtml(
        """<!DOCTYPE html>
    <html><body>
    <p id="status">waiting...</p>
    <script>
    async function run() {
      try {
    
        document.getElementById('status').innerText = 'POST...';
        r = await fetch('mre://test', {method: 'POST', body: '123'});
        console.log('POST OK', await r.json());
        
        //document.getElementById('status').innerText = 'GET...';
        //let r = await fetch('mre://test', {method: 'GET'});
        //console.log('GET OK', await r.json());
    
        document.getElementById('status').innerText = 'Both OK';
      } catch(e) {
        document.getElementById('status').innerText = e.toString();
      }
    }
    setTimeout(run, 1500);
    </script>
    </body></html>""",
        baseUrl=QUrl("https://example.com/"),
    )
    view.resize(600, 400)
    view.show()
    
    print("ready", flush=True)
    QTimer.singleShot(10000, app.quit)
    sys.exit(app.exec())
    
    /usr/bin/uv run /home/pyxiion/Projects/PxModRim/.venv/bin/python /home/pyxiion/Projects/PxModRim/mre_post_crash.py 
    Python: 3.12.13 (main, Jun 11 2026, 04:03:26) [Clang 22.1.3 ]
    PySide6: 6.11.1
    Qt: 6.11.1
    ready
    POST mre://test/
    before requestBody()
    
    Process finished with exit code 139 (interrupted by signal 11:SIGSEGV)
    

    PyQT

    """MRE: PyQt6 QWebEngineUrlSchemeHandler POST requestBody() crash"""
    from __future__ import annotations
    
    import sys
    
    from PyQt6.QtCore import QByteArray, QBuffer, QIODevice, QTimer, QUrl, qVersion
    from PyQt6.QtWebEngineCore import (
        QWebEngineUrlScheme,
        QWebEngineUrlSchemeHandler,
        QWebEngineUrlRequestJob,
        QWebEngineProfile,
    )
    from PyQt6 import QtCore
    
    print(f"PyQt6: {QtCore.PYQT_VERSION_STR}", flush=True)
    print(f"Qt: {qVersion()}", flush=True)
    
    # Register scheme before QApplication
    scheme = QWebEngineUrlScheme(b"mre")
    scheme.setFlags(
        QWebEngineUrlScheme.Flag.SecureScheme
        | QWebEngineUrlScheme.Flag.ContentSecurityPolicyIgnored
        | QWebEngineUrlScheme.Flag.FetchApiAllowed
        | QWebEngineUrlScheme.Flag.CorsEnabled
    )
    scheme.setSyntax(QWebEngineUrlScheme.Syntax.Host)
    QWebEngineUrlScheme.registerScheme(scheme)
    
    from PyQt6.QtWidgets import QApplication
    from PyQt6.QtWebEngineWidgets import QWebEngineView
    
    
    class Handler(QWebEngineUrlSchemeHandler):
        def requestStarted(self, job: QWebEngineUrlRequestJob) -> None:
            print(
                f"{job.requestMethod().data().decode()} {job.requestUrl().toString()}",
                file=sys.stderr, flush=True,
            )
            print("before requestBody()", file=sys.stderr, flush=True)
            body = job.requestBody()
            print("after requestBody()", file=sys.stderr, flush=True)
    
            if body is not None:
                print(f"  body obj: {body}", file=sys.stderr, flush=True)
                print(f"  isOpen: {body.isOpen()}", file=sys.stderr, flush=True)
                if not body.isOpen():
                    body.open(QIODevice.OpenModeFlag.ReadOnly)
                raw = body.readAll().data()
                print(f"  body ({len(raw)} bytes): {raw[:200]}", file=sys.stderr, flush=True)
    
            buf = QBuffer()
            buf.setData(b'{"ok":true}')
            buf.open(QIODevice.OpenModeFlag.ReadOnly)
            buf.setParent(job)
            job.reply(b"application/json", buf)
    
    
    app = QApplication(sys.argv)
    
    handler = Handler()
    QWebEngineProfile.defaultProfile().installUrlSchemeHandler(
        QByteArray(b"mre"), handler
    )
    
    view = QWebEngineView()
    view.setHtml(
        """<!DOCTYPE html>
    <html><body>
    <p id="status">waiting...</p>
    <script>
    async function run() {
      try {
        document.getElementById('status').innerText = 'GET...';
        let r = await fetch('mre://test', {method: 'GET'});
        console.log('GET OK', await r.json());
    
        document.getElementById('status').innerText = 'POST (empty body)...';
        r = await fetch('mre://test', {method: 'POST'});
        console.log('POST OK', await r.json());
    
        document.getElementById('status').innerText = 'POST (with body)...';
        r = await fetch('mre://test', {method: 'POST', body: JSON.stringify({hello:'world'})});
        console.log('POST body OK', await r.json());
    
        document.getElementById('status').innerText = 'All OK ✓';
      } catch(e) {
        document.getElementById('status').innerText = e.toString();
      }
    }
    setTimeout(run, 1500);
    </script>
    </body></html>""",
        baseUrl=QUrl("https://example.com/"),
    )
    view.resize(600, 400)
    view.show()
    
    print("ready", file=sys.stderr, flush=True)
    QTimer.singleShot(10000, app.quit)
    sys.exit(app.exec())
    
    /usr/bin/uv run /home/pyxiion/Projects/RimSort/.venv/bin/python /home/pyxiion/Projects/RimSort/mre_post_crash_pyqt6.py 
    PyQt6: 6.11.0
    Qt: 6.11.1
    ready
    GET mre://test/
    before requestBody()
    after requestBody()
      body obj: <PyQt6.QtCore.QIODevice object at 0x7f251b2b6490>
      isOpen: False
      body (0 bytes): b''
    POST mre://test/
    before requestBody()
    after requestBody()
      body obj: <PyQt6.QtCore.QIODevice object at 0x7f251b2b6530>
      isOpen: False
      body (0 bytes): b''
    POST mre://test/
    before requestBody()
    after requestBody()
      body obj: <PyQt6.QtCore.QIODevice object at 0x7f251b2b6490>
      isOpen: False
      body (17 bytes): b'{"hello":"world"}'
    
    Process finished with exit code 0
    

    GDB bt

    (gdb) bt
    #0  0x00007ffff73723ac in ?? () from /home/pyxiion/Projects/PxModRim/.venv/lib/python3.12/site-packages/PySide6/libpyside6.abi3.so.6.11
    #1  0x00007ffff73730b8 in PySide::getWrapperForQObject(QObject*, _typeobject*) () from /home/pyxiion/Projects/PxModRim/.venv/lib/python3.12/site-packages/PySide6/libpyside6.abi3.so.6.11
    #2  0x00007ffff618f22c in ?? () from /home/pyxiion/Projects/PxModRim/.venv/lib/python3.12/site-packages/PySide6/QtWebEngineCore.abi3.so
    #3  0x00000000018106c3 in cfunction_vectorcall_NOARGS.llvm.10372914493467373164 ()
    #4  0x00000000018154f3 in _PyEval_EvalFrameDefault ()
    #5  0x000000000181199a in method_vectorcall.llvm ()
    #6  0x00007ffff6194c50 in ?? () from /home/pyxiion/Projects/PxModRim/.venv/lib/python3.12/site-packages/PySide6/QtWebEngineCore.abi3.so
    #7  0x00007ffff6194d0a in ?? () from /home/pyxiion/Projects/PxModRim/.venv/lib/python3.12/site-packages/PySide6/QtWebEngineCore.abi3.so
    #8  0x00007fffe8087dae in ?? () from /home/pyxiion/Projects/PxModRim/.venv/lib/python3.12/site-packages/PySide6/Qt/lib/libQt6WebEngineCore.so.6
    
    1 Reply Last reply
    0
    • P Offline
      P Offline
      PyXiion
      wrote last edited by
      #2

      Same crash for 6.10.1, 6.10.3, 6.11.0

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved