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

RemoteVST: process all remaining messages after the process has quit #4371

Closed
wants to merge 1 commit into from
Closed

RemoteVST: process all remaining messages after the process has quit #4371

wants to merge 1 commit into from

Conversation

ghost
Copy link

@ghost ghost commented May 22, 2018

If the process exits, keep processing the remaining messages. Some might be debug messages or a msg that the vst loaded was 32 bits.

(cherry-picked msvc/ng)

@@ -54,7 +54,7 @@ ProcessWatcher::ProcessWatcher( RemotePlugin * _p ) :

void ProcessWatcher::run()
{
while( !m_quit && m_plugin->isRunning() )
while( !m_quit && (m_plugin->messagesLeft() || m_plugin->isRunning()) )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me there's a possibility for a race condition:

  1. m_plugin->messagesLeft() returns false.
  2. VST posts new message and then exits.
  3. m_plugin->isRunning() returns false.
  4. Loop aborts even though there are pending messages.

I think the conditional should just be rearranged so that m_plugin->messagesLeft() is only checked after m_plugin->isRunning():

while( !m_quit && (m_plugin->isRunning() || m_plugin->messagesLeft()) )

I'm not very familiar with the area of the code though, so don't hesitate to point out why I might be wrong about this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heh :) good catch, thanks. (I wanted to write something about why you were wrong but then realized you were right)

Wallacoloo added a commit to Wallacoloo/lmms that referenced this pull request Jun 2, 2018
@Wallacoloo
Copy link
Member

Thanks for the patch! I went ahead and made the adjustment mentioned above, and committed that to master: 4fd8ecd

Credited you by your original username, but if there was any other metadata in the original commit, it was probably lost since I had to reauthor the commit (couldn't pull from the original repo since it's been deleted).

@lukas-w
Copy link
Member

lukas-w commented Jun 24, 2018

@Wallacoloo It looks like this change is ineffective because of a second invalidate() call here:

void RemotePlugin::processFinished( int exitCode,
QProcess::ExitStatus exitStatus )
{
#ifndef SYNC_WITH_SHM_FIFO
invalidate();
#endif
}

I ran into IdVstBasDllFormat messages not being processed when trying to implement 64bit VSTs on Linux. I feel like that invalidate() call can just be removed because ProcessWatcher will call invalidate() eventually, but I'm not actually sure about the reason @jasp00 added it there, nor do I understand what the #ifdef is for.

Do you have any idea how to approach this?

@Wallacoloo
Copy link
Member

@lukas-w Interesting. I didn't dig around to figure out where we decide whether or not to build with SHM_FIFO.

I don't know enough about this area. I'm going to assume you're building with SHM_FIFO undefined, in which case it looks like we're communicating with the remote plugin using sockets.

If we try reading from the socket after the plugin has hung up, can we ever get data from it? I think we can - I think that data still hangs around after the process has exited. If that's the case, I don't understand why we can't still read queued messages from an "invalid" RemotePlugin. Can we just remove the if (!isInvalid()) check from the top of RemotePluginBase::read?

	void read( void * _buf, int _len )
	{
                /* REMOVE THIS CHECK
		if( isInvalid() )
		{
			memset( _buf, 0, _len );
			return;
		}
                */
		lock();
		while( isInvalid() == false &&  //< keep this check to avoid deadlocks
				_len > m_data->endPtr - m_data->startPtr )
		{
			unlock();
#ifndef LMMS_BUILD_WIN32
			usleep( 5 );
#endif
			lock();
		}
		fastMemCpy( _buf, m_data->data + m_data->startPtr, _len );
		m_data->startPtr += _len;
		// nothing left?
		if( m_data->startPtr == m_data->endPtr )
		{
			// then reset to 0
			m_data->startPtr = m_data->endPtr = 0;
		}
		unlock();
	}

On the other hand, if the socket can no longer be read after the remote plugin exits, then we're out of luck. We would need to somehow make sure remote plugins wait until the host reads all messages before exiting - which wouldn't be easy to do if the plugin crashes / etc.

Like I said, I don't know much about this area of LMMS.

sdasda7777 pushed a commit to sdasda7777/lmms that referenced this pull request Jun 28, 2022
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

Successfully merging this pull request may close these issues.

None yet

2 participants