Bug : flet build freezes at ft.app() when using signal handlers or threading
When a Flet app uses Python's signal module or threading module, it works perfectly with flet run but freezes (hangs indefinitely) at ft.app() call after building with flet build macos/windows/linux.
Environment Flet version: 0.25.x (tested) Python version: 3.13 OS: macOS (also likely affects Windows/Linux) Build command: flet build macos Steps to Reproduce ❌ Problematic Code (freezes after build):
import sys import signal import flet as ft import threading
Signal handlers
def signal_handler(sig, frame): print(f"Signal received: {sig}") sys.exit(0)
signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler)
Threading usage
some_thread = threading.Thread(target=some_function, daemon=True) some_thread.start()
EventBus with threading.Lock
class EventBus: _lock = threading.Lock()
def emit(self, event):
with self._lock:
# ... event handling
Main app
def main(page: ft.Page): page.title = "Test App" page.add(ft.Text("Hello"))
This works with flet run but FREEZES after flet build
ft.app(target=main)
✅ Working Code (asyncio-only, Flet native):
import flet as ft import asyncio
Use Flet's native async model
def main(page: ft.Page): page.title = "Test App"
# Use page.run_task for background work
async def background_task():
while True:
await asyncio.sleep(1)
print("Running...")
page.run_task(background_task)
page.add(ft.Text("Hello"))
ft.app(target=main)
Expected Behavior App should start normally after flet build execution Both flet run and built executables should behave identically Actual Behavior flet run: Works perfectly ✅ After flet build macos: App freezes at ft.app() call, no UI appears, process hangs indefinitely ❌ Root Cause Analysis Flet uses a single-threaded async event loop model. When signal handlers or threading primitives are used:
They interfere with Flet's event loop in built executables flet run is more forgiving and handles these conflicts Built executables are stricter and freeze when detecting thread/signal conflicts Solution/Workaround Remove all threading and signals, use Flet's native async patterns:
Remove signal handlers (unnecessary for GUI apps) Replace threading.Thread → page.run_task(async_function) Replace threading.Lock → Not needed (single-threaded model) For blocking I/O → Use asyncio.to_thread(blocking_function) Example:
❌ BEFORE (freezes after build)
import threading
def load_data(): # blocking operation data = requests.get(url).json() return data
thread = threading.Thread(target=load_data) thread.start()
✅ AFTER (works everywhere)
import asyncio
async def load_data_async(): # Non-blocking with asyncio.to_thread data = await asyncio.to_thread( lambda: requests.get(url).json() ) return data
page.run_task(load_data_async)
Impact This issue is critical for developers migrating from Qt/threading-based apps to Flet, as they might unknowingly use threading patterns that work in development but fail in production.
Suggestion Documentation: Add prominent warning about thread/signal incompatibility in build mode Runtime detection: Warn users during flet run if signal handlers or threading are detected Better error message: Instead of silent freeze, show error message about incompatible patterns Related Issues Possibly related to #4060 (frozen application) Similar to #5507 (build hangs)