You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've been trying to implement thread pinning for my AppDaemon apps to address some MQTT performance blocking issues, and the experience has been incredibly frustrating. After days of multiple failed attempts, cryptic error messages, and reading through the documentation several times, I still havent got it working!
My Environment
AppDaemon Version: 4.5.12
Python Version: 3.12.12
Installation Method: Home Assistant Add-on
Apps: 3 apps (including a few mixins) that need thread pinning for performance reasons.
Problem 1: Silent Configuration Failure with Cryptic -1 Errors
What I Tried
I read the documentation about thread pinning and set up what seemed like a straightforward configuration:
appdaemon.yaml:
appdaemon:
total_threads: 10# pin_apps: True # I had this commented out
My apps completely failed to start with these errors:
WARNING AppDaemon: Invalid value for pin_thread (-1) in app: worktracker - discarding callback
ERROR worktracker: Error setting up listeners: Pin thread -1 out of range. Must be between 0 and 9
ERROR Error: AppStartFailure: App 'worktracker' failed to start
ERROR Error: InitializationFail: initialize() method failed for app 'worktracker'
ERROR Error: PinOutofRange: Pin thread -1 out of range. Must be between 0 and 9
The Confusion
Where did -1 come from? I specified pin_thread: 0 in my configuration! The error message gave me no clue about what was actually wrong. I spent a long time searching my code for where -1 might be getting set.
After digging through the documentation again, I found this buried statement:
"The pin_thread directive will be ignored if pin_app is set to false, or if pin_app is not specified and the global setting is to not pin apps."
So apparently when pin_thread is "ignored," it actually gets set to -1 internally, which then causes a crash. This seems like really poor error handling - if my configuration is invalid, I'd expect either:
A clear warning at startup: "pin_thread specified but pinning not enabled"
The directive to actually be ignored (not cause a crash)
Problem 2: Complex Interdependencies Not Validated
After more troubleshooting, I discovered that I also needed to:
Uncomment pin_apps: True in appdaemon.yaml (global setting)
Add pin_threads: 5 to reserve threads for pinned apps
So the working configuration requires THREE different settings across two files:
appdaemon.yaml:
appdaemon:
total_threads: 10pin_apps: true # Required!pin_threads: 5# Also required!
apps.yaml:
worktracker:
module: worktrackerclass: WorkTrackerpin_app: true # Also required!pin_thread: 0
The Problem
None of these interdependencies are validated at configuration load time. AppDaemon happily accepts invalid configurations and only crashes later when apps try to start. There's no "configuration check" that says "You have pin_thread set but pinning isn't properly enabled."
Problem 3: API Method Causes 60-Second Deadlock
What I Tried
After struggling with the YAML configuration, I tried the alternative approach documented in "Per Class Pinning" - using API calls in the initialize() method:
definitialize(self):
# Per Class Pinning as documentedself.set_app_pin(True)
self.set_pin_thread(0)
# Rest of my initialization...self.listen_state(self.on_state_change, self.person_entity)
The documentation says:
"This is achieved using an API call, usually in the initialize() function..."
What Happened
AppDaemon completely hung for 60 seconds, then timed out:
INFO AppDaemon: Calling initialize() for worktracker
[60 second hang...]
WARNING worktracker: Coroutine (<coroutine object ADAPI.set_app_pin at 0x7f947b5970>) took too long (01:00), cancelling the task...
WARNING AppDaemon: Coroutine (<coroutine object Threading.calculate_pin_threads at 0x7f97579f10>) took too long (01:00), cancelling the task...
The Problem
The documentation explicitly suggests using these API calls "usually in the initialize() function," but doing so causes a deadlock. The set_app_pin() method appears to try recalculating thread distribution while the app is still initializing, creating a circular wait.
Either:
This is a bug that needs fixing, or
The documentation needs updating to say "don't call this from initialize()"
Questions
Is the -1 behavior intentional? Should invalid pinning configurations cause crashes with cryptic errors, or should they be validated/warned about at startup?
Is the API deadlock a known issue? Should set_app_pin() work in initialize() as the docs suggest?
Is there an obious way, that I've somehow missed, to configure this? Do we really need three separate settings across two files?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
I've been trying to implement thread pinning for my AppDaemon apps to address some MQTT performance blocking issues, and the experience has been incredibly frustrating. After days of multiple failed attempts, cryptic error messages, and reading through the documentation several times, I still havent got it working!
My Environment
Problem 1: Silent Configuration Failure with Cryptic
-1ErrorsWhat I Tried
I read the documentation about thread pinning and set up what seemed like a straightforward configuration:
appdaemon.yaml:
apps.yaml:
What Happened
My apps completely failed to start with these errors:
The Confusion
Where did
-1come from? I specifiedpin_thread: 0in my configuration! The error message gave me no clue about what was actually wrong. I spent a long time searching my code for where-1might be getting set.After digging through the documentation again, I found this buried statement:
So apparently when
pin_threadis "ignored," it actually gets set to-1internally, which then causes a crash. This seems like really poor error handling - if my configuration is invalid, I'd expect either:Problem 2: Complex Interdependencies Not Validated
Attempt 2: Adding
pin_app: trueI updated my
apps.yamlto includepin_app: true:What Happened
Same
-1errors! Still failing completely.The Discovery
After more troubleshooting, I discovered that I also needed to:
pin_apps: Trueinappdaemon.yaml(global setting)pin_threads: 5to reserve threads for pinned appsSo the working configuration requires THREE different settings across two files:
appdaemon.yaml:
apps.yaml:
The Problem
None of these interdependencies are validated at configuration load time. AppDaemon happily accepts invalid configurations and only crashes later when apps try to start. There's no "configuration check" that says "You have
pin_threadset but pinning isn't properly enabled."Problem 3: API Method Causes 60-Second Deadlock
What I Tried
After struggling with the YAML configuration, I tried the alternative approach documented in "Per Class Pinning" - using API calls in the
initialize()method:The documentation says:
What Happened
AppDaemon completely hung for 60 seconds, then timed out:
The Problem
The documentation explicitly suggests using these API calls "usually in the
initialize()function," but doing so causes a deadlock. Theset_app_pin()method appears to try recalculating thread distribution while the app is still initializing, creating a circular wait.Either:
Questions
Is the
-1behavior intentional? Should invalid pinning configurations cause crashes with cryptic errors, or should they be validated/warned about at startup?Is the API deadlock a known issue? Should
set_app_pin()work ininitialize()as the docs suggest?Is there an obious way, that I've somehow missed, to configure this? Do we really need three separate settings across two files?
All reactions