Skip to content

Asyncio requests are hang in some cases #10312

@jiesou

Description

@jiesou

Bug Description

In the Reproducible Code, as long as that line of code exists, it will cause the async request to keep suspended until the program exits.

Small http request without the large image FormData works fine (return example.com's response), while larger ones do not (they hang).

I I can only suspect there might be an issue with smol::Async.


LLM says :
The async_adapter.rs wraps file descriptors using smol::Async and calls poll_readable(cx) / poll_writable(cx) to register wakers with smol's global reactor. However, Slint's event loop never drives the smol reactor.
When poll_readable/writable returns Pending, the waker is registered with smol's reactor, expecting it to be woken when I/O readiness changes. But since nothing polls the smol reactor, the waker never fires, causing async HTTP operations (like aiohttp requests) to hang indefinitely.
The async adapter depends on smol's background reactor thread (if enabled) or luck with timing. This is unreliable and breaks the fundamental contract of async Rust - that registered wakers will be called when futures become ready.
Expected behavior:

Slint should either:

  1. Drive smol's reactor in its event loop via async_io::Reactor::get().react()
    2 .Integrate directly with Python's selector using add_reader/add_writer
  2. Not use smol at all for the Python bridge

Actual behavior: Network I/O stalls because the reactor polling the file descriptors is never invoked.

Reproducible Code (if applicable)

[ui/app_window.slint]
import { Button, VerticalBox } from "std-widgets.slint";

export component AppWindow inherits Window {
    in-out property<string> counter: "42";
    callback request-increase-value();
    VerticalBox { 
        Text {
            text: "Counter: \{root.counter}";
        }
        Button {
            text: "Increase value";
            clicked => { 
                root.request-increase-value();
            }
        }
     }
}


[main.py]
import slint
import aiohttp
import sys
import os
import numpy as np


class MainWindow(slint.loader.ui.app_window.AppWindow):
    @slint.callback
    async def request_increase_value(self):
        print("Increase value requested")
        async with aiohttp.ClientSession() as session:
            url = "http://example.com/api/upload"
            print(f"upload to {url}")
            
            data = aiohttp.FormData()
            data.add_field('image', np.zeros((640, 640, 3), dtype=np.uint8), filename='capture.jpg', content_type='image/jpeg')
            # Try to comment out this line ^
            async with session.post(url, data=data) as resp:
                text = await resp.text()
                print(f"res status={resp.status}, body={text[:200]}")

main_window = MainWindow()
main_window.show()
main_window.run()

Environment Details

  • Slint Version: 1.14.1b1
  • Platform/OS: Linux (OrangePi OS, X11)
  • Programming Language: Python
  • Backend/Renderer: linuxkms-software
[project]
name = "slint-python-template"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = "==3.12.*"
dependencies = [
    "aiohttp>=3.13.2",
    "numpy>=2.4.0",
    "slint>=1.14.1b1",
]

Product Impact

It took me a afternoon to deal with the problem. 🥲

The workaround seems to be avoiding using @slint.callback

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:language-pythonPython bindings (mS,bO)need triagingIssue that the owner of the area still need to triage

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions