From: Alexandre Ratchov Subject: Re: audio/lmms: Fix memory corruption during MIDI input/output To: izzy Meyer Cc: ports@openbsd.org Date: Mon, 25 May 2026 14:46:39 +0200 On Fri, Apr 25, 2025 at 05:32:33PM -0500, izzy Meyer wrote: > On Thu, 24 Apr 2025 15:33:18 +0200 > Alexandre Ratchov wrote: > > > MIDI output and input are handled on different threads, so a mutex is > > required to serialize access to the mio_hdl structure. > > > > This diff fixes disconnection from sndiod caused by corruption of the > > mio_hdl structure. > > > > While we're at it, fix the input event loop to not stop if a signal is > > received during poll(4). If so just recheck the m_quit flag and retry. > > > > OK? > > > > Thanks for this fix Alexandre. I produce on OpenBSD using LMMS. Tested > on amd64. Seems good from some minimal testing on my production > machine. > I don't remember why, but this diff was forgotten. Here's a refreshed version, with better error handling. OK? Index: Makefile =================================================================== RCS file: /cvs/ports/audio/lmms/Makefile,v diff -u -p -u -p -r1.29 Makefile --- Makefile 13 Feb 2026 12:02:13 -0000 1.29 +++ Makefile 25 May 2026 12:34:20 -0000 @@ -5,7 +5,7 @@ DISTNAME = lmms_$V PKGNAME = lmms-$V WRKDIST = ${WRKDIR}/lmms EXTRACT_SUFX = .tar.xz -REVISION = 1 +REVISION = 2 CATEGORIES = audio Index: patches/patch-include_MidiSndio_h =================================================================== RCS file: patches/patch-include_MidiSndio_h diff -N patches/patch-include_MidiSndio_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-include_MidiSndio_h 25 May 2026 12:34:20 -0000 @@ -0,0 +1,19 @@ +Index: include/MidiSndio.h +--- include/MidiSndio.h.orig ++++ include/MidiSndio.h +@@ -32,6 +32,7 @@ + + #include + #include ++#include + + #include + +@@ -64,6 +65,7 @@ class MidiSndio : public MidiClientRaw, public QThread + virtual void run(void); + + private: ++ QMutex m_hdlMutex; + struct mio_hdl *m_hdl; + volatile bool m_quit; + } ; Index: patches/patch-src_core_midi_MidiSndio_cpp =================================================================== RCS file: patches/patch-src_core_midi_MidiSndio_cpp diff -N patches/patch-src_core_midi_MidiSndio_cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_core_midi_MidiSndio_cpp 25 May 2026 12:34:20 -0000 @@ -0,0 +1,61 @@ +␘Index: src/core/midi/MidiSndio.cpp +--- src/core/midi/MidiSndio.cpp.orig ++++ src/core/midi/MidiSndio.cpp +@@ -42,6 +42,7 @@ + + MidiSndio::MidiSndio( void ) : + MidiClientRaw(), ++ m_hdlMutex(), + m_quit( false ) + { + QString dev = probeDevice(); +@@ -86,7 +87,9 @@ QString MidiSndio::probeDevice( void ) + + void MidiSndio::sendByte( const unsigned char c ) + { ++ m_hdlMutex.lock(); + mio_write( m_hdl, &c, 1 ); ++ m_hdlMutex.unlock(); + } + + +@@ -96,20 +99,33 @@ void MidiSndio::run( void ) + nfds_t nfds; + char buf[0x100], *p; + size_t n; ++ int revents; + int ret; ++ + while( m_quit == false && m_hdl ) + { ++ m_hdlMutex.lock(); + nfds = mio_pollfd( m_hdl, &pfd, POLLIN ); ++ m_hdlMutex.unlock(); + ret = poll( &pfd, nfds, 100 ); +- if ( ret < 0 ) ++ if ( ret < 0 ) { ++ if (errno == EINTR) ++ continue; ++ fprintf(stderr, "sndio: poll: %s\n", strerror(errno)); + break; +- if ( !ret || !( mio_revents( m_hdl, &pfd ) & POLLIN ) ) +- continue; +- n = mio_read( m_hdl, buf, sizeof(buf) ); +- if ( !n ) +- { ++ } ++ m_hdlMutex.lock(); ++ revents = mio_revents( m_hdl, &pfd ); ++ if (revents & POLLHUP) { ++ fprintf(stderr, "sndio: device disconnected\n"); ++ m_hdlMutex.unlock(); + break; + } ++ if (revents & POLLIN) { ++ n = mio_read( m_hdl, buf, sizeof(buf) ); ++ } else ++ n = 0; ++ m_hdlMutex.unlock(); + for (p = buf; n > 0; n--, p++) + { + parseData( *p );