spatialaudio / jackclient-python

🂻 JACK Audio Connection Kit (JACK) Client for Python :snake:
https://jackclient-python.readthedocs.io/
MIT License
131 stars 26 forks source link

JackOpenError when (re)creating clients with identical name #98

Closed HaHeho closed 2 years ago

HaHeho commented 3 years ago

I have recently noticed some very annoying behavior with the Jack server "clogging up" on client names. The critical application is that a client is created (usually does something) and is destroyed afterwards. This is then repeated for a considerable amount of times with an identical name of the client. Although this seems like a pretty bonkers use case, we actually rely on doing it (in a current implementation at least). Nevertheless, I would expect this to be possible and handled by the server without problems. Right?

I created the a simple script which provokes the behavior.

import jack

i = 0
while True:
    i += 1

    # name = f'Client{i:d}'  # this runs infinitely
    name = f'Client'  # this ALWAYS fails for the 99th instance ???

    print(f'Test {i:d}: creating "{name}" ...')
    client = jack.Client(name=name)
    client.activate()
    client.deactivate()
    client.close()
    del client

Executing the script results in the following trailing output and error:

...
Test 97: creating "Client" ...
Test 98: creating "Client" ...
Test 99: creating "Client" ...
Cannot open Client client
JackShmReadWritePtr1::~JackShmReadWritePtr1 - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
Traceback (most recent call last):
  File "jack_test.py", line 11, in <module>
    client = jack.Client(name=name)
  File ".../jack.py", line 213, in __init__
    raise JackOpenError(name, self._status)
jack.JackOpenError: Error initializing "Client": <jack.Status 0x21: failure, server_error>

The surprising thing (to me at least) is that this fails at the 99th client. And this is always reproduced in the exact same way.

On very annoying aspect is that this client name is now blocked indefinitely. An continues to be blocked even after restarting the Jack server. I did not find a possibility to instantiate a client with the given name again. This is indeed a problem when using tools like ecasound which do not let you determine the instantiated Jack client name (this is also how I encountered the problem). The easiest way to reset the behavior is to log out and in of the OS session (or restart), which is still very disruptive. Is there an easier option to get this reset?

HaHeho commented 3 years ago

Can somebody else confirm the behavior? My testing was done on macOS 10.15.7, jackd 1.9.16 (via the new installer) and jack-client 0.5.3.

I very much assume that this error has nothing to do with the Jack Python API, since I also encountered this when instantiating ecasound via shell scripts. However, this was the most straight forward way to test the behavior to me. Maybe we can help to resolve the issue upstream by narrowing it down first.

I did not encounter this problem (at least so systematically) before jackd 1.9.16. Maybe the provided binaries are not perfect yet and are causing the issue here. I think testing the latest version, but built locally in the traditional way, would be the first case to check whether it behaves differently. Doing this on my dev system is inconvenient though.

@mgeier do you have a convenient way of testing this on different Jack versions and OS?!

C0nsultant commented 3 years ago

This is reproducible upstream without the Python binding. It's a problem I've faced on Windows since at least 1.9.11. I reported this at https://github.com/jackaudio/jack2/issues/658 together with a reproducer (not really a convenient way of testing).

HaHeho commented 2 years ago

Resolved with https://github.com/jackaudio/jack2/pull/788.