mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Clarified some shutdown behaviour in ConnectedChildProcess
This commit is contained in:
parent
f22317695b
commit
f4cf0c0ef4
2 changed files with 49 additions and 38 deletions
|
|
@ -30,6 +30,11 @@ static const char* killMessage = "__ipc_k_";
|
|||
static const char* pingMessage = "__ipc_p_";
|
||||
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)
|
||||
{
|
||||
return "--" + commandLineUniqueID + ":";
|
||||
|
|
@ -46,11 +51,6 @@ struct ChildProcessPingThread : public Thread,
|
|||
pingReceived();
|
||||
}
|
||||
|
||||
static bool isPingMessage (const MemoryBlock& m) noexcept
|
||||
{
|
||||
return memcmp (m.getData(), pingMessage, specialMessageSize) == 0;
|
||||
}
|
||||
|
||||
void pingReceived() noexcept { countdown = timeoutMs / 1000 + 1; }
|
||||
void triggerConnectionLostMessage() { triggerAsyncUpdate(); }
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ private:
|
|||
{
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
if (--countdown <= 0 || ! sendPingMessage (MemoryBlock (pingMessage, specialMessageSize)))
|
||||
if (--countdown <= 0 || ! sendPingMessage ({ pingMessage, specialMessageSize }))
|
||||
{
|
||||
triggerConnectionLostMessage();
|
||||
break;
|
||||
|
|
@ -110,7 +110,7 @@ private:
|
|||
{
|
||||
pingReceived();
|
||||
|
||||
if (m.getSize() != specialMessageSize || ! isPingMessage (m))
|
||||
if (m.getSize() != specialMessageSize || ! isMessageType (m, pingMessage))
|
||||
owner.handleMessageFromSlave (m);
|
||||
}
|
||||
|
||||
|
|
@ -124,12 +124,7 @@ ChildProcessMaster::ChildProcessMaster() {}
|
|||
|
||||
ChildProcessMaster::~ChildProcessMaster()
|
||||
{
|
||||
if (connection != nullptr)
|
||||
{
|
||||
sendMessageToSlave (MemoryBlock (killMessage, specialMessageSize));
|
||||
connection->disconnect();
|
||||
connection.reset();
|
||||
}
|
||||
killSlaveProcess();
|
||||
}
|
||||
|
||||
void ChildProcessMaster::handleConnectionLost() {}
|
||||
|
|
@ -143,10 +138,10 @@ bool ChildProcessMaster::sendMessageToSlave (const MemoryBlock& mb)
|
|||
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());
|
||||
|
||||
|
|
@ -154,13 +149,15 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin
|
|||
args.add (executable.getFullPathName());
|
||||
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);
|
||||
|
||||
if (connection->isConnected())
|
||||
{
|
||||
sendMessageToSlave (MemoryBlock (startMessage, specialMessageSize));
|
||||
sendMessageToSlave ({ startMessage, specialMessageSize });
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -170,6 +167,18 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin
|
|||
return false;
|
||||
}
|
||||
|
||||
void ChildProcessMaster::killSlaveProcess()
|
||||
{
|
||||
if (connection != nullptr)
|
||||
{
|
||||
sendMessageToSlave ({ killMessage, specialMessageSize });
|
||||
connection->disconnect();
|
||||
connection.reset();
|
||||
}
|
||||
|
||||
childProcess.reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct ChildProcessSlave::Connection : public InterprocessConnection,
|
||||
private ChildProcessPingThread
|
||||
|
|
@ -201,23 +210,14 @@ private:
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
|
@ -245,12 +245,12 @@ bool ChildProcessSlave::initialiseFromCommandLine (const String& commandLine,
|
|||
const String& commandLineUniqueID,
|
||||
int timeoutMs)
|
||||
{
|
||||
String prefix (getCommandLinePrefix (commandLineUniqueID));
|
||||
auto prefix = getCommandLinePrefix (commandLineUniqueID);
|
||||
|
||||
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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -135,7 +135,10 @@ public:
|
|||
*/
|
||||
ChildProcessMaster();
|
||||
|
||||
/** Destructor. */
|
||||
/** Destructor.
|
||||
Note that the destructor calls killSlaveProcess(), but doesn't wait for
|
||||
the child process to finish terminating.
|
||||
*/
|
||||
virtual ~ChildProcessMaster();
|
||||
|
||||
/** 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
|
||||
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,
|
||||
const String& commandLineUniqueID,
|
||||
int timeoutMs = 0,
|
||||
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.
|
||||
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&);
|
||||
|
||||
private:
|
||||
ChildProcess childProcess;
|
||||
ScopedPointer<ChildProcess> childProcess;
|
||||
|
||||
struct Connection;
|
||||
friend struct Connection;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue