DEF_TEST(IpcMessageQueue, SendRecvMessage)
{
	try {
		IpcMessageQueuePtr host = IpcMessageQueue::Create("utest");
		IpcMessageQueuePtr client = IpcMessageQueue::Open("utest");

		bool ret = host->WriteMessage("test", "hello");
		TEST_ASSERT(ret, "unexpected timeout when writing message");

		std::string type, msg;
		ret = client->ReadMessage(type, msg);
		TEST_ASSERT(ret, "unexpected timeout when reading message");

		TEST_ASSERT(type == "test", "unexpected type, expected 'test' but got: '" << type << "'");
		TEST_ASSERT(msg == "hello", "unexpected message contents, expected 'hello' but got: '" << msg << "'");

	} catch (IpcEx ex) {
		TEST_EX("IpcEx, " << ex.GetMsg());
	}
	
}
Пример #2
0
	void StartSession(const std::string& shmName, PlatformPtr platform, IpcMessageQueuePtr hostQueue){
		for(auto& plugin : plugins){
			try { 
				std::string messageQueueName = UuidGenerator::Create()->GenerateUuid(RandChar::Create());
				FlogExpD(messageQueueName);
				plugin.messageQueue = IpcMessageQueue::Create(messageQueueName, 2, 1024 * 1024 * 32, 4, 1024 * 16);

				plugin.process = platform->StartProcess(plugin.executable, {messageQueueName, shmName}, plugin.directory);
				plugin.started = true;

				SendArguments(plugin);
			} catch (PlatformEx e) {
				FlogE("could not start plugin: " << plugin.executable << " because: " << e.GetMsg());
				plugin.started = false;
				hostQueue->WriteMessage(Str("error -1 " << plugin.name), "could not start process");
			}
		}
	}
Пример #3
0
	void ProcessMessages(PlatformPtr platform, IpcMessageQueuePtr hostQueue, bool waitReady, int timeout){
		for(auto& plugin : plugins){
			if(!plugin.started)
				continue;
		
			bool done = false;

			while(!done){
				bool ret = false;
				bool isRunning = true; // = false;
				const int period = 100;
				int deadSincePeriods = 0;
				
				for(int i = 0; i < timeout / period; i++){
					if(i > period * 10)
						FlogW("waiting for slow plugin: " << plugin.executable);

					ret = plugin.messageQueue->GetReadBuffer([&](const std::string& type, const char* buffer, size_t size){
						if(Tools::StartsWith(type, "results")){
							// results message, relay to host
							FlogD("relaying results from: " << plugin.executable);

							if(hostQueue->GetWriteQueueSize() >= (int)size){
								char* outBuffer = hostQueue->GetWriteBuffer();
								memcpy(outBuffer, buffer, size);
								hostQueue->ReturnWriteBuffer(Str(type << " " << plugin.name), &outBuffer, size);
							}else{
								hostQueue->WriteMessage(Str("error 0 " << plugin.name), "result too big for frameserver/host message queue");
								FlogW("result too big for frameserver/host message queue, plugin: " << plugin.executable << " " << plugin.name);
							}

							if(!waitReady)
								done = true;
						}

						else if(type == "status"){
							// plugin is ready for next frame
							// TODO actually check if the message says "ready"
							if(waitReady)
								done = true;
						}

						else if(Tools::StartsWith(type, "error")){
							// error
							FlogD("relaying error from: " << plugin.executable);
							done = true;
							plugin.started = false;
							hostQueue->WriteMessage(Str(type << " " << plugin.name), buffer);
						}
						
						else{
							// unknown
							FlogW("unknown message type: " << type << " from plugin: " << plugin.name);
							done = true;
							plugin.started = false;
						}
					}, period);

					// The deadSincePeriods counter exists to prevent a race condition where the frameserver queue read times out
					// because the plugin has acquired a buffer for writing a result. If the plugin then manages to terminate
					// before the process->IsRunning check in the frameserver, the reported result (or other message) would be ignored.

					// If the process has been dead the last 10 periods (1 is probably enough) we can safely assume that there are no
					// result messages in the queue waiting for us, and since the plugin process is dead, we can exit the loop.

					deadSincePeriods += plugin.process->IsRunning() ? 0 : 1;
					isRunning = deadSincePeriods < 10;

					if(ret || !isRunning)
						break;
				}


				if(!isRunning){
					// process exited
					hostQueue->WriteMessage(Str("error 0 " << plugin.name), "process exited");
					FlogW("process exited, plugin: " << plugin.executable << " " << plugin.name);

					plugin.started = false;
					break;
				}

				else if(!ret){
					// timeout occured
					hostQueue->WriteMessage(Str("error 0 " << plugin.name), "timeout while processing frames");
					FlogW("timeout, plugin: " << plugin.executable << " " << plugin.name);

					plugin.started = false;
					break;
				}
			}
		}
	}