python-eel / Eel

A little Python library for making simple Electron-like HTML/JS GUI apps
MIT License
6.38k stars 583 forks source link

Memory leak: calling functions async (not invoking the return function) leaves keys in the _call_return_values object #539

Closed nosachamos closed 2 years ago

nosachamos commented 2 years ago

Eel version 1.4.0

Describe the bug When a call from Python to JS is performed in a async manner (not invoking the return function so that Python is not blocked), the return value is stored in the _call_return_values object and never removed.

Inside eel, the only place where this object is cleaned is inside the return function:

def _call_return(call):
    global _js_result_timeout
    call_id = call['call']

    def return_func(callback=None, error_callback=None):
        if callback is not None:
            _call_return_callbacks[call_id] = (callback, error_callback)
        else:
            for w in range(_js_result_timeout):
                if call_id in _call_return_values:
                    return _call_return_values.pop(call_id)
                sleep(0.001)
    return return_func

if return_func is not invoked, the keys and values just accumulate on this object indefinitely. In tests I'm running here I see them just grow:

image

This could be the cause for some of the performance problems reported by others after running several hours.

Expected behavior values should be cleaned / deleted once the call is completed, perhaps after a certain time to still allow the caller to retrieve the return value. For e.g., after 10 seconds in this object, they should be removed. Or something along these lines. The current implementation will not run for very long before running into memory issues.

nosachamos commented 2 years ago

I realize that I need to call the returned function no matter what. But that was not clear from the docs. This one is resolved but I found another memory leak situation that is valid. Will open a second bug.