Browse Source

Clarified some shutdown behaviour in ConnectedChildProcess

tags/2021-05-28
jules 8 years ago
parent
commit
f4cf0c0ef4
2 changed files with 49 additions and 38 deletions
  1. +36
    -36
      modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp
  2. +13
    -2
      modules/juce_events/interprocess/juce_ConnectedChildProcess.h

+ 36
- 36
modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp View File

@@ -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())
{ {


+ 13
- 2
modules/juce_events/interprocess/juce_ConnectedChildProcess.h View File

@@ -135,7 +135,10 @@ public:
*/ */
ChildProcessMaster(); ChildProcessMaster();
/** Destructor. */
/** Destructor.
Note that the destructor calls killSlaveProcess(), but doesn't wait for
the child process to finish terminating.
*/
virtual ~ChildProcessMaster(); virtual ~ChildProcessMaster();
/** Attempts to launch and connect to a slave process. /** Attempts to launch and connect to a slave process.
@@ -152,12 +155,20 @@ public:
If this all works, the method returns true, and you can begin sending and If this all works, the method returns true, and you can begin sending and
receiving messages with the slave process. receiving messages with the slave process.
If a child process is already running, this will call killSlaveProcess() and
start a new one.
*/ */
bool launchSlaveProcess (const File& executableToLaunch, bool launchSlaveProcess (const File& executableToLaunch,
const String& commandLineUniqueID, const String& commandLineUniqueID,
int timeoutMs = 0, int timeoutMs = 0,
int streamFlags = ChildProcess::wantStdOut | ChildProcess::wantStdErr); int streamFlags = ChildProcess::wantStdOut | ChildProcess::wantStdErr);
/** Sends a kill message to the slave, and disconnects from it.
Note that this won't wait for it to terminate.
*/
void killSlaveProcess();
/** This will be called to deliver a message from the slave process. /** This will be called to deliver a message from the slave process.
The call will probably be made on a background thread, so be careful with your thread-safety! The call will probably be made on a background thread, so be careful with your thread-safety!
*/ */
@@ -176,7 +187,7 @@ public:
bool sendMessageToSlave (const MemoryBlock&); bool sendMessageToSlave (const MemoryBlock&);
private: private:
ChildProcess childProcess;
ScopedPointer<ChildProcess> childProcess;
struct Connection; struct Connection;
friend struct Connection; friend struct Connection;


Loading…
Cancel
Save