Lmms: Hang when closing related to WinMM MIDI driver

Created on 27 Oct 2017  路  22Comments  路  Source: LMMS/lmms

Configuration: Windows 7 SP1 32-bit, LMMS V1.2.0RC4, M-Audio MIDISport 2+2, driver version 6.1.3

When closing LMMS, a "zombie" LMMS process is left in the Task Manager which cannot be killed. These chew up about 40MB at a time. If LMMS is started and stopped repeatedly, more copies of the process will show up in the Task Manager. In testing, I found that changing the audio back-end to "Dummy" did not make a difference in this issue, but changing the MIDI back-end to "Dummy" enabled LMMS to close successfully. If I changed it back to WinMM, LMMS left a dead process running. There are no error messages displayed, and it leaves no entries in the Windows system logs.

I have other applications that I use with MIDI (OpenMPT, saVihoST, SimplePiano) which use the MIDISport 2+2 driver directly, and they don't seem to have any difficulty with my setup. I would be curious about other MIDI USB devices and WinMM, but I don't have any others to test. Anybody with USB keyboard controllers might want to have a look at your task manager!

lmms_task_manager

bug windows

Most helpful comment

@vwren thanks for the research and the hint. It appears we're attempting to call that in the MidiWinMM destructor: https://github.com/LMMS/lmms/blob/stable-1.2/src/core/midi/MidiWinMM.cpp#L253

The major difference is that the article you've posted closed by handle whereas we loop over all devices and close. Also, the Microsoft API says that problems can occur if buffers are still busy.

"If there are input buffers that have been sent by using the midiInAddBuffer function and have not been returned to the application, the close operation will fail. To return all pending buffers through the callback function, use the midiInReset function."

This likely exposes a leak, but to patch it we may benefit from calling midiInReset and then midiInClose.

All 22 comments

I can confirm the findings. It looks like it might be related to the M-Audio MIDI drivers. I have two sound devices that I can use for testing:

  • M-Audio Audiophile 2496 (PCI card)
  • Behringer U-PHORIA UMC204 HD (USB audio interface)

During the tests I have varied what device is set as the default sound device in Windows 8.1 and the MIDI driver that's used by LMMS:

Default sound device|MIDI driver|Result
------------|------------|----------
M-Audio|WinMM|Zombie processes
M-Audio|Dummy|Terminates correctly
Behringer|WinMM|Terminates correctly
Behringer|Dummy|Terminates correctly

Unfortunately I don't have the means to debug under Windows. Perhaps we can create a build that logs some info for LMMS' WinMM driver?

Then LMMS should hang in void MidiWinMM::closeDevices(). As far as I know, there are two possibilities if that's right:

  1. Hang in Win32 API function for some reason
  2. Stuck in while loop(less likely to be the issue)

I am not a programmer, but I wonder if this could be relevant (found on MSDN and related to WinMM and MIDI鈥攅ven better, the person having the problem was using an M-Audio card). The symptoms certainly sound similar.

https://social.msdn.microsoft.com/Forums/en-US/091b793e-ce74-40fb-8a77-f99d9f4e3aa5/how-to-close-an-audio-device?forum=vbgeneral

@vwren thanks for the research and the hint. It appears we're attempting to call that in the MidiWinMM destructor: https://github.com/LMMS/lmms/blob/stable-1.2/src/core/midi/MidiWinMM.cpp#L253

The major difference is that the article you've posted closed by handle whereas we loop over all devices and close. Also, the Microsoft API says that problems can occur if buffers are still busy.

"If there are input buffers that have been sent by using the midiInAddBuffer function and have not been returned to the application, the close operation will fail. To return all pending buffers through the callback function, use the midiInReset function."

This likely exposes a leak, but to patch it we may benefit from calling midiInReset and then midiInClose.

So something like:

    QMapIterator<HMIDIIN, QString> i( m_inputDevices );
    while( i.hasNext() )
    {
        midiInReset( i.next().key() );
        midiInClose( i.next().key() );
    }

This should also be done for midiOut, I'm thinking, to ensure that all buffers are freed before closing.

QMapIterator<HMIDIIN, QString> i( m_inputDevices );
while( i.hasNext() )
{
    midiInReset( i.next().key() );
    midiInClose( i.next().key() );
}

QMapIterator<HMIDIOUT, QString> o( m_outputDevices );
while( o.hasNext() )
{
    midiOutReset( o.next().key() );
    midiOutClose( o.next().key() );
}

Yes.

PS. I'm not hacking this by the way. I'm not anywhere near a Windows computer.

~Here are Windows 32-bit/64-bit executables with the patch:
https://github.com/PhysSong/lmms/releases/tag/v1.2.0-rc50~ Deleted.

@PhysSong i will install and see if i can get mem-leaks on win 32

Closing down i get this every time
closecrash
That is bad, but something new now occur.
Getting this crash message, has always meant that there will be orphan remoteVST.dll's, that is left as memory leaks, for every VST in the project.
There is none!
I have not seen this before.
I looks like lmms does shut down, but there is still a 'abnormality' that cast the win-error-popup.
There is also a LADSPA load problem
lostladspas
Is you build limited, because that could influence the shutdown-process imo.
...
Forgot to say that the win-error-popup comes even without any VSTs at all. An empty project, cast the win-error too.

@musikBear Thank you for testing. I'll test it and see if I can reproduce the crash.

@PhysSong Unfortunately I am still getting the hanging processes with your patched executables.

@PhysSong i ran into even more issues. The test-release cant load all factory-instruments. Trying to load free-boy a not found error pop-up, and then the application crash completely. This time with orphans.
Again i ask you: Have you compiled all parts? Imo that is necessary, for this issue

This should also be done for midiOut, I'm thinking, to ensure that all buffers are freed before closing.

Ardour stopped using midiOutReset() after getting hangs: https://github.com/Ardour/ardour/commit/d10913e2de736b8b34d5efe12548c50296add378

It's possible that midiOutReset() is unstable. I know that SimplePiano uses the Reset/Close destructor for MIDI out, and for MIDI in, uses midiInStop(), midiInReset(), midiInClose(). I have never had it hang on me when closing, but it would take a larger sample size to have more confidence in it. (on further testing, I was wrong鈥攖he MIDI is unstable and it does hang, but the image is only 1.3MB and didn't cause much memory loss. So the destructor might be to blame)

Another issue might be caused by the Midi Stream manager. http://mastersonicarts.uniroma2.it/wp-content/uploads/2016/01/MIDI-Specification-11.pdf (search for "midiOutReset" and read the WARNING paragraph after it). I kind of doubt that Ardour is using the stream manager, but I have no evidence one way or the other. It would appear that midiOutReset() is useful mainly for shutting down stuck notes, so its function is not orthogonal to midiInReset() which frees up buffer space. I'm finding differing opinions, but there seems to be some consensus around the idea that midiOutReset() is broken and unnecessary, especially if there's another mechanism for handling stuck notes.

@vwren @michaelgregorius Here's a new build without midiOutReset(midiInReset only):
https://github.com/PhysSong/lmms/releases/tag/v1.2.0-rc51/

@PhysSong, with version RC51 I now get a crash when I close LMMS (but the process is gone :wink:). Here's some more information:

Problemsignatur:
  Problemereignisname:  APPCRASH
  Anwendungsname:   lmms.exe
  Anwendungsversion:    0.0.0.0
  Anwendungszeitstempel:    adf0ade8
  Fehlermodulname:  Qt5Core.dll
  Fehlermodulversion:   5.4.2.0
  Fehlermodulzeitstempel:   00000020
  Ausnahmecode: c0000005
  Ausnahmeoffset:   0000000000080cc0
  Betriebsystemversion: 6.3.9600.2.0.0.256.48
  Gebietsschema-ID: 1031
  Zusatzinformation 1:  6a60
  Zusatzinformation 2:  6a60f3846abeaee1799080a162c2d495
  Zusatzinformation 3:  f8b8
  Zusatzinformation 4:  f8b89ef7aa7e11afcf9615006ec5ac3d

Lesen Sie unsere Datenschutzbestimmungen online:
  http://go.microsoft.com/fwlink/?linkid=280262

Wenn die Onlinedatenschutzbestimmungen nicht verf眉gbar sind, lesen Sie unsere Datenschutzbestimmungen offline:
  C:\WINDOWS\system32\de-DE\erofflps.txt

I found that I did something wrong with iterators. I've fixed the iterator issue and created new builds.
@vwren @michaelgregorius New binaries available: https://github.com/PhysSong/lmms/releases/tag/v1.2.0-rc52

@PhysSong, I have installed the 64 bit version of LMMS 1.2.0-RC52 and I am still getting a crash when I close the application even if I do not switch to the M-Audio interface. Steps are:

  1. Start LMMS 1.2.0-RC52.
  2. Quit with CTRL+Q.

Additional info (does not look like it will help much though):

Problemsignatur:
  Problemereignisname:  APPCRASH
  Anwendungsname:   lmms.exe
  Anwendungsversion:    0.0.0.0
  Anwendungszeitstempel:    ade0add8
  Fehlermodulname:  lmms.exe
  Fehlermodulversion:   0.0.0.0
  Fehlermodulzeitstempel:   ade0add8
  Ausnahmecode: c0000005
  Ausnahmeoffset:   00000000000a7db0
  Betriebsystemversion: 6.3.9600.2.0.0.256.48
  Gebietsschema-ID: 1031
  Zusatzinformation 1:  7560
  Zusatzinformation 2:  7560d411dbc17020b70fb50fb8691831
  Zusatzinformation 3:  4fe6
  Zusatzinformation 4:  4fe6b3f41321af4df47f57eb001c90d6

@michaelgregorius QMapIterator seems to behave somewhat strange, so I needed to work around it. Here's a new 64bit installer: lmms-1.2.0-rc6.14-win64.exe
I hope it will work this time.

@PhysSong With lmms-1.2.0-rc6.14-win64.exe the crashes are gone and I also do not get any hanging processes anymore when I close the application. Looks like we can close this issue. :+1: :tada:

@vwren Can you please test with the latest RC if the issue is fixed for you as well?

I'll just upload 32bit binary and open a pull request. Good to hear that's working!

Was this page helpful?
0 / 5 - 0 ratings