Move mpos.apps.good_stack_size() to TaskManager.good_stack_size()

Trying to get every app-facing API as part of an object.
This commit is contained in:
Thomas Farstrike
2026-01-24 19:10:51 +01:00
parent 7b65ec7301
commit 43eb8220c8
9 changed files with 30 additions and 58 deletions
@@ -2,8 +2,7 @@ import time
import lvgl as lv
import _thread
from mpos import Activity, Intent, MposKeyboard, WifiService, CameraActivity, DisplayMetrics, CameraManager
import mpos.apps
from mpos import Activity, Intent, MposKeyboard, WifiService, CameraActivity, DisplayMetrics, CameraManager, TaskManager
class WiFi(Activity):
"""
@@ -101,7 +100,7 @@ class WiFi(Activity):
self.busy_scanning = True
self.scan_button.add_state(lv.STATE.DISABLED)
self.scan_button_label.set_text(self.scan_button_scanning_text)
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self.scan_networks_thread, ())
def refresh_list(self):
@@ -179,7 +178,7 @@ class WiFi(Activity):
print("Not attempting connect because busy_connecting.")
else:
self.busy_connecting = True
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self.attempt_connecting_thread, (ssid, password))
def attempt_connecting_thread(self, ssid, password):
-35
View File
@@ -6,13 +6,6 @@ import traceback
import mpos.info
import mpos.ui
def good_stack_size():
stacksize = 24*1024 # less than 20KB crashes on desktop when doing heavy apps, like LightningPiggy's Wallet connections
import sys
if sys.platform == "esp32":
stacksize = 16*1024
return stacksize
# Run the script in the current thread:
# Returns True if successful
def execute_script(script_source, is_file, classname, cwd=None):
@@ -81,34 +74,6 @@ def execute_script(script_source, is_file, classname, cwd=None):
traceback.print_exception(type(e), e, tb)
return False
""" Unused:
# Run the script in a new thread:
# NOTE: check if the script exists here instead of launching a new thread?
def execute_script_new_thread(scriptname, is_file):
print(f"main.py: execute_script_new_thread({scriptname},{is_file})")
try:
# 168KB maximum at startup but 136KB after loading display, drivers, LVGL gui etc so let's go for 128KB for now, still a lot...
# But then no additional threads can be created. A stacksize of 32KB allows for 4 threads, so 3 in the app itself, which might be tight.
# 16KB allows for 10 threads in the apps, but seems too tight for urequests on unix (desktop) targets
# 32KB seems better for the camera, but it forced me to lower other app threads from 16 to 12KB
#_thread.stack_size(24576) # causes camera issue...
# NOTE: This doesn't do anything if apps are started in the same thread!
if "camtest" in scriptname:
print("Starting camtest with extra stack size!")
stack=32*1024
elif "appstore" in scriptname:
print("Starting appstore with extra stack size!")
stack=24*1024 # this doesn't do anything because it's all started in the same thread
else:
stack=16*1024 # 16KB doesn't seem to be enough for the AppStore app on desktop
stack = mpos.apps.good_stack_size()
print(f"app.py: setting stack size for script to {stack}")
_thread.stack_size(stack)
_thread.start_new_thread(execute_script, (scriptname, is_file))
except Exception as e:
print("main.py: execute_script_new_thread(): error starting new thread thread: ", e)
"""
# Returns True if successful
def start_app(fullname):
from .content.package_manager import PackageManager
@@ -6,7 +6,7 @@
# Uses _thread for non-blocking background playback/recording (separate thread from UI)
import _thread
import mpos.apps
from ..task_manager import TaskManager
class AudioFlinger:
@@ -164,7 +164,7 @@ class AudioFlinger:
on_complete=on_complete
)
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self._playback_thread, (stream,))
return True
@@ -208,7 +208,7 @@ class AudioFlinger:
on_complete=on_complete
)
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self._playback_thread, (stream,))
return True
@@ -285,7 +285,7 @@ class AudioFlinger:
)
print("AudioFlinger: Starting recording thread...")
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self._recording_thread, (stream,))
print("AudioFlinger: Recording thread started successfully")
return True
@@ -16,6 +16,7 @@ import task_handler
import mpos.ui
import mpos.ui.focus_direction
from ..task_manager import TaskManager
# Pin configuration
SPI_BUS = 2
@@ -386,7 +387,7 @@ def startup_wow_effect():
except Exception as e:
print(f"Startup effect error: {e}")
_thread.stack_size(mpos.apps.good_stack_size()) # default stack size won't work, crashes!
_thread.stack_size(TaskManager.good_stack_size()) # default stack size won't work, crashes!
_thread.start_new_thread(startup_wow_effect, ())
print("fri3d_2024.py finished")
+3 -2
View File
@@ -9,8 +9,9 @@ import mpos.ui
from .content.package_manager import PackageManager
from .ui.appearance_manager import AppearanceManager
from .ui.display_metrics import DisplayMetrics
import mpos.ui.topmenu
import mpos.ui.topmenu
from .task_manager import TaskManager
# White text on black logo works (for dark mode) and can be inverted (for light mode)
@@ -124,7 +125,7 @@ except Exception as e:
try:
from mpos.net.wifi_service import WifiService
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(WifiService.auto_connect, ())
except Exception as e:
print(f"Couldn't start WifiService.auto_connect thread because: {e}")
+9 -4
View File
@@ -26,10 +26,6 @@ class TaskManager:
print("Not starting TaskManager because it's been disabled.")
return
cls.keep_running = True
# New thread works but LVGL isn't threadsafe so it's preferred to do this in the same thread:
#_thread.stack_size(mpos.apps.good_stack_size())
#_thread.start_new_thread(asyncio.run, (self._asyncio_thread(100), ))
# Same thread works, although it blocks the real REPL, but aiorepl works:
asyncio.run(TaskManager._asyncio_thread(10)) # 100ms is too high, causes lag. 10ms is fine. not sure if 1ms would be better...
@classmethod
@@ -70,3 +66,12 @@ class TaskManager:
@staticmethod
def wait_for(awaitable, timeout):
return asyncio.wait_for(awaitable, timeout)
@staticmethod
def good_stack_size():
stacksize = 24*1024 # less than 20KB crashes on desktop when doing heavy apps, like LightningPiggy's Wallet connections
import sys
if sys.platform == "esp32":
stacksize = 16*1024
return stacksize
+4 -1
View File
@@ -1,5 +1,8 @@
# Lightweight replacement for CPython's Thread module
import _thread
from .task_manager import TaskManager
import mpos.apps
class Thread:
@@ -21,7 +24,7 @@ class Thread:
# small stack sizes 8KB gives segfault directly
# 22KB or less is too tight on desktop, 23KB and more is fine
#stacksize = 24*1024
stacksize = mpos.apps.good_stack_size()
stacksize = TaskManager.good_stack_size()
#stacksize = 20*1024
print(f"starting thread with stacksize {stacksize}")
_thread.stack_size(stacksize)
+3 -5
View File
@@ -2,12 +2,10 @@ import unittest
import _thread
import time
from mpos import App, PackageManager
import mpos.apps
from mpos import App, PackageManager, TaskManager
from websocket import WebSocketApp
# demo_multiple_ws.py
import asyncio
import aiohttp
@@ -137,7 +135,7 @@ class TestTwoWebsockets(unittest.TestCase):
asyncio.run(self.main())
def test_it(self):
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self.newthread, ())
time.sleep(10)
@@ -253,6 +251,6 @@ class TestCrashingSeparateThreads(): # Disabled
def test_it(self):
for url in self.WS_URLS:
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self.newthread, (url,))
time.sleep(15)
+2 -2
View File
@@ -3,7 +3,7 @@ import _thread
import time
from mpos import App, PackageManager
import mpos.apps
from mpos import TaskManager
from websocket import WebSocketApp
@@ -136,7 +136,7 @@ class TestTwoWebsockets(unittest.TestCase):
asyncio.run(self.main())
def test_it(self):
_thread.stack_size(mpos.apps.good_stack_size())
_thread.stack_size(TaskManager.good_stack_size())
_thread.start_new_thread(self.newthread, ())
time.sleep(10)