Crashes when InterprocessConnection::sendMessage(const MemoryBlock & message);


#1

Hello,
I created two different plugins and connected them together by InterprocessConnection

And it works very nice if they are connected. But the problem is when there is only one plugin launched, and another is turned off (not launched). As I understand in that situation there is no connection - but I am not sure if I understand it properly.

The problem is that if there is no connection and I call (by clicking button) sendMessage my whole plugin host crashes. “Crashed” I mean there is twisting coloured beach ball (os x system icon, that it’s thinking) and I can’t even move any window of whole host. So that’s why I want to prevent calling sendMessage if there is no connection. But the problem is, I don’t know how.

I found out that connectToPipe("myUniquePluginName", -1)) always return true. Even if second plugin is not running. isConnected() also always return true. So how to check if there is connection? Or how to check if other plugin is running and they are connected together?


#2

First of all: did you debug it? This show’s you what’s actually happening.

connectToPipe("myUniquePluginName", -1)) always returning true is strange, but I can reproduce it! That might be a bug. But there’s a quite simple solution.

But first: Logic isn’t crashing, it’s freezing. The reason is, that you are creating a loop which won’t stop. So it’s sucking all of the CPU ressources -> freeze. You connect to the pipe with a timeout of -1, so it will retry again and again to send the message, which will of course fail as there’s no connection established. Setting the timeout to let’s say 100ms will only block it for that amount.

Checking the connection: once a connection has been established, the connectionMade() method of both parties will be called. There you can set a flag, that the connection was actually made. If it drops, connectionLost() is called. That way you can check, if the connection is currently established.

The sendMessage(...) will also return a true, telling you if it has been sent successfully. If you want to be even more sure, let the receiver send back an ACK.


#3
  1. OK, I will try your suggestions. Thanks a lot for your patience.
  2. Whad do you mean “ACK”?
  3. “Freeze” !!! Yes!!! that’s the word I couldn’t find :slight_smile: thanks

#4


If your received message could be interpreted successfully, you can sent something like a “thumbs up” back to the sender, to let it know, everything’s just fine :slight_smile:


#5

Hey Daniel.
There is something wrong in what you said. Freezing does not happen when I call connectToPipe("uniqueSecondPluginName", -1)).

Freezing happens when I call sendMessage(someMemBlock);

That’s why when I change -1 to 100 in connectToPipe it does not help. And also connectToPipe("uniqueSecondPluginName", 100)) return true even if the SecondPlugin is not running.


#6

And need to be mentioned: connectionMade() also always is called after connectToPipe or createPipe.

What returns false is only (and always) createPipe("pajImpulse", -1, true)).
Can’t figure it out the behaviour of those functions.


#7

And one more should be mentioned: connectionLost() is never called.
When I launch second plugin, in first should be called connectionMade() (but it’s already called before launch second).
And when I remove second plugin from process, there in the first one should be called connectionLost(). But it does not. No matter what happen.

One thing is still not mentioned: for debuging I mainly use JUCE example Plugin Host (not Logic Pro). I will check for a moment those behaviours in Logic and I will inform you.


#8

I’ve just checked. In Logic Pro X, connectionLost() is also never called, but connectionMade() is always called.


#9

One more behaviour I’ve just found.
If I call createPipe in first plugin, and in second connectToPipe, and both have pipeReceiveMessageTimeoutMs=20000, and I run both plugins (in less then 20000ms), they are working together only in those 20000ms, after that time connectionLost() is called in both plugins.


#10

OK it looks like I almost understand it (or just have solution for me) but still can’t figure it out why connectToPipe and createPipe(.... , false) always return true


#11

And one more question. If I want both plugin be able to control each other, does it matter in which plugin I call createPipe() and in which connectToPipe?
Maybe should I call both methods in both plugins?


#12

That’s indeed a strange behavior.

When looking at the connectToPipe(...) code, after some calls, NamedPipe::openInternal (pipename, false, false) is called. Here’s the code of that method:

It’s called in a way that no new pipe should be opened (first false), it only should try to connect. With this call, the function always returns true (see line 214), which it shouldn’t. The consequence: InterprocessConnection assumes that the connection was made and therefore also returns true.

Maybe someone from the JUCE team can tell us, if this behavior is intended?

Edit: Minimal code example:
sender is an instance of a class which inherits from `InterprocessConnection? No pipe has been opened by any other InterprocessConnection instance.

if (sender.connectToPipe("something", 100))
    {
        DBG ("Successfully connected to pipe!");
    }

    if (sender.isConnected())
    {
        DBG ("Sender says it is connected");
    }

After Sender says it is connected the connectionMade() is called, and exactly 100ms later connectionLost() is called.


#13

Hello, to be strictly precise. I am not sure if I just don’t understand or you made mistake. In your example “connectionMade()” is called NOT after “Sender says it is connected” BUT after “Successfully connected to pipe!”.
Am I right or not?


#14

Yea, I guess that depends on when the MessageThread kicks in. But that doesn‘t change the problem :-/


#15

That behaviour was not intended. Here’s a fix:


#18

Sorry but it doesn’t help.
Still:
connectToPipe("uniqueName", -1)

always return true.
I copied all content of those three files on github, and on my drive removed everything from those files and paste from github. And after that I open my project in Projucer, and clicked save and open in xCode. And in xCode I checked those 3 files random lines if they are for sure updated. And they are. But the problem still occurs.


#19

And the same with isConnected() .
Also always return true.


#20

Are you really sure that you’re picking up the latest changes? If so, are you really sure that the named pipe doesn’t exist?

I added some unit tests which check that connectToPipe("uniqueName", -1) will behave as expected, and they passed on a number of different machines.

A “NamedPipe” is a special kind of file that can act as a communication channel. If you’ve previously created this file, and then failed to clean it up because your app crashed or otherwise shut down incorrectly, then it might still exist. In which case the connectToPipe behaviour you are seeing would be correct.

A much better way of managing your files is to use git itself, rather than copy-pasting content from a web browser. There’s no guarantee that this approach will work, as there may be other changes that a specific commit depends upon.


#21

I am sure pipe doesn’t exist, because when I call senfMessage() my host is freeze. I found that it happens only when other plugin with createPipe() is not launched.


#22

So how to use git in that case? I always download new version from Juce.com, or update by Projucer, but not sure how to do that by github? Should I just delete my whole JUCE folder from Application folder on my Mac, and then download whole zip file from https://github.com/WeAreROLI/JUCE and then copy JUCE-master folder to my Application folder?