SteamDeckHomebrew / decky-loader

A plugin loader for the Steam Deck.
https://decky.xyz
GNU General Public License v2.0
4.69k stars 163 forks source link

After some time plugin backend calls never resolve and decky-loader goes into a weird state #158

Closed popsUlfr closed 2 years ago

popsUlfr commented 2 years ago

Hi,

while writing a new plugin for taking notes : https://github.com/popsUlfr/SDH-Notebook I've run into the issue where calls to the python backend never return after some time. I'm not sure if I did something very wrong in my code but once it happens the other plugins fail to function properly. decky-loader itself for instance is unable to check for updates and stays in a perpetual Updates spinner state :

image

Restarting plugin_loader.service seems to fix it until it happens again.

I added timeout checks to my backend calls and it seems to be stuck at the importReactPlugin() step:

async importPlugin(name, version) {
    if (this.reloadLock) {
        this.log('Reload currently in progress, adding to queue', name);
        this.pluginReloadQueue.push({ name, version: version });
        return;
    }
    try {
        this.reloadLock = true;
        this.log(`Trying to load ${name}`);
        this.unloadPlugin(name);
        if (name.startsWith('$LEGACY_')) {
            await this.importLegacyPlugin(name.replace('$LEGACY_', ''));
        }
        else {
            await this.importReactPlugin(name, version); // <= this call
        }
        this.deckyState.setPlugins(this.plugins);
        this.log(`Loaded ${name}`);
    }
    catch (e) {
        throw e;
    }
    finally {
        this.reloadLock = false;
        const nextPlugin = this.pluginReloadQueue.shift();
        if (nextPlugin) {
            this.importPlugin(nextPlugin.name, nextPlugin.version);
        }
    }
}
async importReactPlugin(name, version) {
    let res = await fetch(`http://127.0.0.1:1337/plugins/${name}/frontend_bundle`, {
        credentials: 'include',
        headers: {
            Authentication: window.deckyAuthToken,
        },
    });
    if (res.ok) {
        let plugin = await eval(await res.text())(this.createPluginAPI(name)); // <= blocks here
        this.plugins.push({
            ...plugin,
            name: name,
            version: version,
        });
    }
    else
        throw new Error(`${name} frontend_bundle not OK`);
}
/8501.js:2 Error: Backend call timed out
    at eval (eval at importReactPlugin (localhost:1337/frontend/index.js:1125), <anonymous>:19187:33)
    at eval (eval at importReactPlugin (localhost:1337/frontend/index.js:1125), <anonymous>:19544:3)
    at PluginLoader.importReactPlugin (localhost:1337/frontend/index.js:1125)
    at async PluginLoader.importPlugin (localhost:1337/frontend/index.js:1101)
console.error @ /8501.js:2

EDIT1: I just noticed this in the plugin_loader logs:

Aug 28 16:24:14 steamdeck PluginLoader[5871]: [base_events][ERROR]: Task exception was never retrieved
Aug 28 16:24:14 steamdeck PluginLoader[5871]: future: <Task finished name='Task-64' coro=<PluginWrapper._listen_for_method_call() done, defined at plugin.py:67> exception=ValueError('Separator is found, but chunk is longer than limit')>
Aug 28 16:24:14 steamdeck PluginLoader[5871]: Traceback (most recent call last):
Aug 28 16:24:14 steamdeck PluginLoader[5871]:   File "asyncio/streams.py", line 525, in readline
Aug 28 16:24:14 steamdeck PluginLoader[5871]:   File "asyncio/streams.py", line 620, in readuntil
Aug 28 16:24:14 steamdeck PluginLoader[5871]: asyncio.exceptions.LimitOverrunError: Separator is found, but chunk is longer than limit
Aug 28 16:24:14 steamdeck PluginLoader[5871]: During handling of the above exception, another exception occurred:
Aug 28 16:24:14 steamdeck PluginLoader[5871]: Traceback (most recent call last):
Aug 28 16:24:14 steamdeck PluginLoader[5871]:   File "plugin.py", line 69, in _listen_for_method_call
Aug 28 16:24:14 steamdeck PluginLoader[5871]:   File "asyncio/streams.py", line 534, in readline
Aug 28 16:24:14 steamdeck PluginLoader[5871]: ValueError: Separator is found, but chunk is longer than limit

So it would be an issue with the string length in this particular use case ?

TrainDoctor commented 2 years ago

@popsUlfr if you could join the SteamDeckHomebrew discord I'd love to communicate more with you there.

popsUlfr commented 2 years ago

@TrainDoctor Oki, I just joined :)

BTW in the meantime I exposed a quick http server with aiohttp to POST and GET the drawings and that works pretty well. But yeah, it seems the argument size is a bit restrictive currently with method calling. It would be nice to have a streaming API for the bigger data chunks.