|
|
@@ -30,6 +30,11 @@ static const char* killMessage = "__ipc_k_"; |
|
|
static const char* pingMessage = "__ipc_p_";
|
|
|
static const char* pingMessage = "__ipc_p_";
|
|
|
enum { specialMessageSize = 8, defaultTimeoutMs = 8000 };
|
|
|
enum { specialMessageSize = 8, defaultTimeoutMs = 8000 };
|
|
|
|
|
|
|
|
|
|
|
|
static inline bool isMessageType (const MemoryBlock& mb, const char* messageType) noexcept
|
|
|
|
|
|
{
|
|
|
|
|
|
return mb.matches (messageType, (size_t) specialMessageSize);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
static String getCommandLinePrefix (const String& commandLineUniqueID)
|
|
|
static String getCommandLinePrefix (const String& commandLineUniqueID)
|
|
|
{
|
|
|
{
|
|
|
return "--" + commandLineUniqueID + ":";
|
|
|
return "--" + commandLineUniqueID + ":";
|
|
|
@@ -46,11 +51,6 @@ struct ChildProcessPingThread : public Thread, |
|
|
pingReceived();
|
|
|
pingReceived();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
static bool isPingMessage (const MemoryBlock& m) noexcept
|
|
|
|
|
|
{
|
|
|
|
|
|
return memcmp (m.getData(), pingMessage, specialMessageSize) == 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void pingReceived() noexcept { countdown = timeoutMs / 1000 + 1; }
|
|
|
void pingReceived() noexcept { countdown = timeoutMs / 1000 + 1; }
|
|
|
void triggerConnectionLostMessage() { triggerAsyncUpdate(); }
|
|
|
void triggerConnectionLostMessage() { triggerAsyncUpdate(); }
|
|
|
|
|
|
|
|
|
@@ -68,7 +68,7 @@ private: |
|
|
{
|
|
|
{
|
|
|
while (! threadShouldExit())
|
|
|
while (! threadShouldExit())
|
|
|
{
|
|
|
{
|
|
|
if (--countdown <= 0 || ! sendPingMessage (MemoryBlock (pingMessage, specialMessageSize)))
|
|
|
|
|
|
|
|
|
if (--countdown <= 0 || ! sendPingMessage ({ pingMessage, specialMessageSize }))
|
|
|
{
|
|
|
{
|
|
|
triggerConnectionLostMessage();
|
|
|
triggerConnectionLostMessage();
|
|
|
break;
|
|
|
break;
|
|
|
@@ -110,7 +110,7 @@ private: |
|
|
{
|
|
|
{
|
|
|
pingReceived();
|
|
|
pingReceived();
|
|
|
|
|
|
|
|
|
if (m.getSize() != specialMessageSize || ! isPingMessage (m))
|
|
|
|
|
|
|
|
|
if (m.getSize() != specialMessageSize || ! isMessageType (m, pingMessage))
|
|
|
owner.handleMessageFromSlave (m);
|
|
|
owner.handleMessageFromSlave (m);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -124,12 +124,7 @@ ChildProcessMaster::ChildProcessMaster() {} |
|
|
|
|
|
|
|
|
ChildProcessMaster::~ChildProcessMaster()
|
|
|
ChildProcessMaster::~ChildProcessMaster()
|
|
|
{
|
|
|
{
|
|
|
if (connection != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
sendMessageToSlave (MemoryBlock (killMessage, specialMessageSize));
|
|
|
|
|
|
connection->disconnect();
|
|
|
|
|
|
connection.reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
killSlaveProcess();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
void ChildProcessMaster::handleConnectionLost() {}
|
|
|
void ChildProcessMaster::handleConnectionLost() {}
|
|
|
@@ -143,10 +138,10 @@ bool ChildProcessMaster::sendMessageToSlave (const MemoryBlock& mb) |
|
|
return false;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
bool ChildProcessMaster::launchSlaveProcess (const File& executable, const String& commandLineUniqueID, int timeoutMs, int streamFlags)
|
|
|
|
|
|
|
|
|
bool ChildProcessMaster::launchSlaveProcess (const File& executable, const String& commandLineUniqueID,
|
|
|
|
|
|
int timeoutMs, int streamFlags)
|
|
|
{
|
|
|
{
|
|
|
connection.reset();
|
|
|
|
|
|
jassert (childProcess.kill());
|
|
|
|
|
|
|
|
|
killSlaveProcess();
|
|
|
|
|
|
|
|
|
auto pipeName = "p" + String::toHexString (Random().nextInt64());
|
|
|
auto pipeName = "p" + String::toHexString (Random().nextInt64());
|
|
|
|
|
|
|
|
|
@@ -154,13 +149,15 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin |
|
|
args.add (executable.getFullPathName());
|
|
|
args.add (executable.getFullPathName());
|
|
|
args.add (getCommandLinePrefix (commandLineUniqueID) + pipeName);
|
|
|
args.add (getCommandLinePrefix (commandLineUniqueID) + pipeName);
|
|
|
|
|
|
|
|
|
if (childProcess.start (args, streamFlags))
|
|
|
|
|
|
|
|
|
childProcess.reset (new ChildProcess());
|
|
|
|
|
|
|
|
|
|
|
|
if (childProcess->start (args, streamFlags))
|
|
|
{
|
|
|
{
|
|
|
connection = new Connection (*this, pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs);
|
|
|
connection = new Connection (*this, pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs);
|
|
|
|
|
|
|
|
|
if (connection->isConnected())
|
|
|
if (connection->isConnected())
|
|
|
{
|
|
|
{
|
|
|
sendMessageToSlave (MemoryBlock (startMessage, specialMessageSize));
|
|
|
|
|
|
|
|
|
sendMessageToSlave ({ startMessage, specialMessageSize });
|
|
|
return true;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -170,6 +167,18 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin |
|
|
return false;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ChildProcessMaster::killSlaveProcess()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (connection != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
sendMessageToSlave ({ killMessage, specialMessageSize });
|
|
|
|
|
|
connection->disconnect();
|
|
|
|
|
|
connection.reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
childProcess.reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
//==============================================================================
|
|
|
struct ChildProcessSlave::Connection : public InterprocessConnection,
|
|
|
struct ChildProcessSlave::Connection : public InterprocessConnection,
|
|
|
private ChildProcessPingThread
|
|
|
private ChildProcessPingThread
|
|
|
@@ -201,23 +210,14 @@ private: |
|
|
{
|
|
|
{
|
|
|
pingReceived();
|
|
|
pingReceived();
|
|
|
|
|
|
|
|
|
if (m.getSize() == specialMessageSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isPingMessage (m))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
if (isMessageType (m, pingMessage))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
if (memcmp (m.getData(), killMessage, specialMessageSize) == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
triggerConnectionLostMessage();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
if (isMessageType (m, killMessage))
|
|
|
|
|
|
return triggerConnectionLostMessage();
|
|
|
|
|
|
|
|
|
if (memcmp (m.getData(), startMessage, specialMessageSize) == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
owner.handleConnectionMade();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
if (isMessageType (m, startMessage))
|
|
|
|
|
|
return owner.handleConnectionMade();
|
|
|
|
|
|
|
|
|
owner.handleMessageFromMaster (m);
|
|
|
owner.handleMessageFromMaster (m);
|
|
|
}
|
|
|
}
|
|
|
@@ -245,12 +245,12 @@ bool ChildProcessSlave::initialiseFromCommandLine (const String& commandLine, |
|
|
const String& commandLineUniqueID,
|
|
|
const String& commandLineUniqueID,
|
|
|
int timeoutMs)
|
|
|
int timeoutMs)
|
|
|
{
|
|
|
{
|
|
|
String prefix (getCommandLinePrefix (commandLineUniqueID));
|
|
|
|
|
|
|
|
|
auto prefix = getCommandLinePrefix (commandLineUniqueID);
|
|
|
|
|
|
|
|
|
if (commandLine.trim().startsWith (prefix))
|
|
|
if (commandLine.trim().startsWith (prefix))
|
|
|
{
|
|
|
{
|
|
|
String pipeName (commandLine.fromFirstOccurrenceOf (prefix, false, false)
|
|
|
|
|
|
.upToFirstOccurrenceOf (" ", false, false).trim());
|
|
|
|
|
|
|
|
|
auto pipeName = commandLine.fromFirstOccurrenceOf (prefix, false, false)
|
|
|
|
|
|
.upToFirstOccurrenceOf (" ", false, false).trim();
|
|
|
|
|
|
|
|
|
if (pipeName.isNotEmpty())
|
|
|
if (pipeName.isNotEmpty())
|
|
|
{
|
|
|
{
|
|
|
|