26enum { magicCoordWorkerConnectionHeader = 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 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)
56 void pingReceived() noexcept { countdown = timeoutMs / 1000 + 1; }
59 virtual bool sendPingMessage (
const MemoryBlock&) = 0;
60 virtual void pingFailed() = 0;
67 Atomic<int> countdown;
69 void handleAsyncUpdate()
override { pingFailed(); }
75 if (--countdown <= 0 || ! sendPingMessage ({ pingMessage, specialMessageSize }))
77 triggerConnectionLostMessage();
85 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessPingThread)
89struct ChildProcessCoordinator::Connection final :
public InterprocessConnection,
90 private ChildProcessPingThread
94 ChildProcessPingThread (timeout),
100 ~Connection()
override
102 cancelPendingUpdate();
106 using ChildProcessPingThread::startPinging;
109 void connectionMade()
override {}
110 void connectionLost()
override { owner.handleConnectionLost(); }
112 bool sendPingMessage (
const MemoryBlock& m)
override {
return owner.sendMessageToWorker (m); }
113 void pingFailed()
override { connectionLost(); }
115 void messageReceived (
const MemoryBlock& m)
override
119 if (m.getSize() != specialMessageSize || ! isMessageType (m, pingMessage))
120 owner.handleMessageFromWorker (m);
125 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection)
140 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
141 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
142 handleMessageFromSlave (
mb);
143 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
144 JUCE_END_IGNORE_WARNINGS_MSVC
149 if (connection !=
nullptr)
150 return connection->sendMessage (
mb);
167 childProcess = [&]() -> std::shared_ptr<ChildProcess>
170 return ChildProcessManager::getInstance()->createAndStartManagedChildProcess (
args,
streamFlags);
172 auto p = std::make_shared<ChildProcess>();
180 if (childProcess !=
nullptr)
182 connection.reset (
new Connection (*
this,
pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs));
184 if (connection->isConnected())
186 connection->startPinging();
199 if (connection !=
nullptr)
202 connection->disconnect();
206 childProcess.reset();
211 private ChildProcessPingThread
215 ChildProcessPingThread (timeout),
221 ~Connection()
override
223 cancelPendingUpdate();
228 using ChildProcessPingThread::startPinging;
233 void connectionMade()
override {}
234 void connectionLost()
override { owner.handleConnectionLost(); }
236 bool sendPingMessage (
const MemoryBlock& m)
override {
return owner.sendMessageToCoordinator (m); }
237 void pingFailed()
override { connectionLost(); }
239 void messageReceived (
const MemoryBlock& m)
override
243 if (isMessageType (m, pingMessage))
246 if (isMessageType (m, killMessage))
247 return triggerConnectionLostMessage();
249 if (isMessageType (m, startMessage))
250 return owner.handleConnectionMade();
252 owner.handleMessageFromCoordinator (m);
255 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Connection)
267 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
268 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
269 handleMessageFromMaster (
mb);
270 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
271 JUCE_END_IGNORE_WARNINGS_MSVC
276 if (connection !=
nullptr)
277 return connection->sendMessage (
mb);
292 .upToFirstOccurrenceOf (
" ",
false,
false).trim();
296 connection.reset (
new Connection (*
this,
pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs));
298 if (connection->isConnected())
299 connection->startPinging();
305 return connection !=
nullptr;
void triggerAsyncUpdate()
void cancelPendingUpdate() noexcept
ChildProcessCoordinator()
virtual ~ChildProcessCoordinator()
bool sendMessageToWorker(const MemoryBlock &)
virtual void handleMessageFromWorker(const MemoryBlock &)
virtual void handleConnectionLost()
bool launchWorkerProcess(const File &executableToLaunch, const String &commandLineUniqueID, int timeoutMs=0, int streamFlags=ChildProcess::wantStdOut|ChildProcess::wantStdErr)
bool sendMessageToCoordinator(const MemoryBlock &)
virtual ~ChildProcessWorker()
virtual void handleMessageFromCoordinator(const MemoryBlock &mb)
bool initialiseFromCommandLine(const String &commandLine, const String &commandLineUniqueID, int timeoutMs=0)
virtual void handleConnectionLost()
virtual void handleConnectionMade()
void disconnect(int timeoutMs=-1, Notify notify=Notify::yes)
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)
static OperatingSystemType getOperatingSystemType()
bool wait(double timeOutMilliseconds) const
Thread(const String &threadName, size_t threadStackSize=osDefaultStackSize)
bool threadShouldExit() const
bool stopThread(int timeOutMilliseconds)