Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client::new() returns error -50 after 6 calls #32

Open
sourcebox opened this issue Jun 3, 2021 · 1 comment
Open

Client::new() returns error -50 after 6 calls #32

sourcebox opened this issue Jun 3, 2021 · 1 comment

Comments

@sourcebox
Copy link

My application uses the midir crate that uses coremidi as a dependency. The original issue is tracked here Boddlnagg/midir#86

The reason for continously creating a client for scanning the ports because the cross-platform midir crate does not support change notifications yet.

While there is a workaround for the problem, it still would be nice to address the issue if possible. I would expect that the acquired client resource is closed at the end of each loop iteration as the variable goes out of scope.

Demo code:

use coremidi::Client;

fn main() {
    loop {
        let client = Client::new("test midi client");

        match client {
            Ok(client) => {
                println!("{:?}", &client);
            }
            Err(error) => {
                println!("{:?}", error);
            }
        }

        std::thread::sleep(std::time::Duration::from_millis(1000));
    }
}
@chris-zen
Copy link
Owner

Hi @sourcebox, thanks for the report.

I've been investigating it a bit. Apparently the Drop for Client is working fine and the client is disposed at CoreMIDI level.

With this code:

impl Drop for Client {
    fn drop(&mut self) {
        println!("Dropping client ...");
        let status = unsafe { MIDIClientDispose(self.object.0) };
        println!("{}", status);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test() {
        let mut counter = 0;
        loop {
            let client = Client::new("test midi client");
            counter += 1;

            match client.as_ref() {
                Ok(client) => {
                    println!("{}, {:?}", counter, client);
                }
                Err(error) => {
                    println!("{:?}", error);
                    break;
                }
            }

            std::thread::sleep(std::time::Duration::from_millis(1000));
        }
    }
}

I see this:

1, Client { object: Object(bc29041), callback: BoxedCallback(0x0) }
Dropping client ...
0
2, Client { object: Object(bc29042), callback: BoxedCallback(0x0) }
Dropping client ...
0
3, Client { object: Object(bc29043), callback: BoxedCallback(0x0) }
Dropping client ...
0
4, Client { object: Object(bc29044), callback: BoxedCallback(0x0) }
Dropping client ...
0
5, Client { object: Object(bc29045), callback: BoxedCallback(0x0) }
Dropping client ...
0
6, Client { object: Object(bc29046), callback: BoxedCallback(0x0) }
Dropping client ...
0
7, Client { object: Object(bc29047), callback: BoxedCallback(0x0) }
Dropping client ...
0
8, Client { object: Object(bc29048), callback: BoxedCallback(0x0) }
Dropping client ...
0
-50

But reading the docs I just found a possible cause for the problem that it would be out of my control:

https://developer.apple.com/documentation/coremidi/1495335-midiclientdispose#discussion

Don’t explicitly dispose of your client; the system automatically disposes all clients when an app terminates.
However, if you call this method to dispose the last or only client owned by an app,
the MIDI server may exit if there are no other clients remaining in the system.
If this occurs, all subsequent calls by your app to MIDIClientCreate(_:_:_:_:) and MIDIClientCreateWithBlock(_:_:_:) fail.

So apparently, clients are not supposed to be created and destroyed that frequently, but instead live for the whole lifecycle of your app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants