26enum { magicMastSlaveConnectionHeader = 0x712baf04 };
28static const char* startMessage =
"__ipc_st";
29static const char* killMessage =
"__ipc_k_";
30static const char* pingMessage =
"__ipc_p_";
31enum { specialMessageSize = 8, defaultTimeoutMs = 8000 };
33static inline bool isMessageType (
const MemoryBlock& mb,
const char* messageType)
noexcept
35 return mb.matches (messageType, (
size_t) specialMessageSize);
38static String getCommandLinePrefix (
const String& commandLineUniqueID)
40 return "--" + commandLineUniqueID +
":";
46struct ChildProcessPingThread :
public Thread,
49 ChildProcessPingThread (
int timeout) :
Thread (
"IPC ping"), timeoutMs (timeout)
54 void pingReceived() noexcept { countdown = timeoutMs / 1000 + 1; }
57 virtual bool sendPingMessage (
const MemoryBlock&) = 0;
58 virtual void pingFailed() = 0;
63 Atomic<int> countdown;
65 void handleAsyncUpdate()
override { pingFailed(); }
71 if (--countdown <= 0 || ! sendPingMessage ({ pingMessage, specialMessageSize }))
73 triggerConnectionLostMessage();
81 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessPingThread)
85struct ChildProcessMaster::Connection :
public InterprocessConnection,
86 private ChildProcessPingThread
90 ChildProcessPingThread (timeout),
97 ~Connection()
override
103 void connectionMade()
override {}
104 void connectionLost()
override { owner.handleConnectionLost(); }
106 bool sendPingMessage (
const MemoryBlock& m)
override {
return owner.sendMessageToSlave (m); }
107 void pingFailed()
override { connectionLost(); }
109 void messageReceived (
const MemoryBlock& m)
override
113 if (m.getSize() != specialMessageSize || ! isMessageType (m, pingMessage))
114 owner.handleMessageFromSlave (m);
119 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection)
134 if (connection !=
nullptr)
135 return connection->sendMessage (
mb);
156 connection.reset (
new Connection (*
this,
pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs));
158 if (connection->isConnected())
172 if (connection !=
nullptr)
175 connection->disconnect();
179 childProcess.reset();
184 private ChildProcessPingThread
188 ChildProcessPingThread (timeout),
195 ~Connection()
override
203 void connectionMade()
override {}
204 void connectionLost()
override { owner.handleConnectionLost(); }
206 bool sendPingMessage (
const MemoryBlock& m)
override {
return owner.sendMessageToMaster (m); }
207 void pingFailed()
override { connectionLost(); }
209 void messageReceived (
const MemoryBlock& m)
override
213 if (isMessageType (m, pingMessage))
216 if (isMessageType (m, killMessage))
217 return triggerConnectionLostMessage();
219 if (isMessageType (m, startMessage))
220 return owner.handleConnectionMade();
222 owner.handleMessageFromMaster (m);
225 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection)
237 if (connection !=
nullptr)
238 return connection->sendMessage (
mb);
253 .upToFirstOccurrenceOf (
" ",
false,
false).trim();
257 connection.reset (
new Connection (*
this,
pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs));
259 if (! connection->isConnected())
264 return connection !=
nullptr;
void add(const ElementType &newElement)
void triggerAsyncUpdate()
bool sendMessageToSlave(const MemoryBlock &)
virtual ~ChildProcessMaster()
bool launchSlaveProcess(const File &executableToLaunch, const String &commandLineUniqueID, int timeoutMs=0, int streamFlags=ChildProcess::wantStdOut|ChildProcess::wantStdErr)
virtual void handleConnectionLost()
bool initialiseFromCommandLine(const String &commandLine, const String &commandLineUniqueID, int timeoutMs=0)
virtual void handleConnectionMade()
virtual ~ChildProcessSlave()
virtual void handleConnectionLost()
bool sendMessageToMaster(const MemoryBlock &)
InterprocessConnection(bool callbacksOnMessageThread=true, uint32 magicMessageHeaderNumber=0xf2b49e2c)
bool createPipe(const String &pipeName, int pipeReceiveMessageTimeoutMs, bool mustNotExist=false)
bool connectToPipe(const String &pipeName, int pipeReceiveMessageTimeoutMs)
static String toHexString(IntegerType number)
bool wait(int timeOutMilliseconds) const
Thread(const String &threadName, size_t threadStackSize=0)
bool threadShouldExit() const
bool stopThread(int timeOutMilliseconds)