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

midiOutUnprepareHeader intermittently hangs on Windows during repeated large sysex sends #333

Open
insolace opened this issue Mar 6, 2024 · 1 comment

Comments

@insolace
Copy link
Contributor

insolace commented Mar 6, 2024

I tried submitting a pull request but did not have permissions.

Starting at line 3184 of RtMidi.cpp:

// Unprepare the buffer and MIDIHDR.
while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof ( MIDIHDR ) ) ) Sleep( 1 );

This line of code is problematic and can cause our application to crash during our firmware update process, when we are sending multiple reboot commands in between large sysex payloads. Our current workaround is to delete the RtMidi in/out objects and then recreate them, otherwise depending on the state of the update process things can hang.

We'd prefer if there was better error handling and/or a timeout inside of this loop. Here is a simple timeout that would be better if there was a method to change the duration:

int timeOut = 0;
// Unprepare the buffer and MIDIHDR.
while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof ( MIDIHDR ) ) )
{
    if (timeOut++ > 25000)
        break;
    Sleep( 1 );
}
@insolace
Copy link
Contributor Author

insolace commented Mar 7, 2024

It looks like another issue references this loop but did not encounter the same bug the we did:

#250

Debugging this further, my suggested timeout code does not actually prevent the application from hanging/crashing. It would seem that having a device reboot after receiving a large sysex payload can create situations where calling midiOutUnprepareHeader hangs, and there's no method in the API to check the validity of the handle or the buffer before calling it.

Our current workaround is to send the firmware, wait for the midi ports to change to confirm that the device has rebooted, and then stop the application with a user dialog/ok that then kills and relaunches the application. Otherwise if we try to send sysex without the kill/relaunch, there's a 50/50 chance that calling midiOutUnprepareHeader will crash the application, even if we delete / recreate the rtmidi object.

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

1 participant