/* * Copyright (c) 2011-2014, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "TestPlatform.h" #include "FullIo.hpp" #include #include #include #include #include #include #include using namespace std; const int iDefaultPortNumber = 5001; // Starts test-platform in blocking mode static bool startBlockingTestPlatform(const char *filePath, int portNumber, string &strError) { // Init semaphore sem_t sem; sem_init(&sem, false, 0); // Create param mgr CTestPlatform testPlatform(filePath, portNumber, sem); // Start platformmgr if (!testPlatform.load(strError)) { sem_destroy(&sem); return false; } // Block here sem_wait(&sem); sem_destroy(&sem); return true; } static void notifyParent(int parentFd, bool success) { if (not utility::fullWrite(parentFd, &success, sizeof(success))) { cerr << "Unable to warn parent process of load " << (success ? "success" : "failure") << ": " << strerror(errno) << endl; assert(false); } } // Starts test-platform in daemon mode static bool startDaemonTestPlatform(const char *filePath, int portNumber, string &strError) { // Pipe used for communication between the child and the parent processes int pipefd[2]; if (pipe(pipefd) == -1) { strError = "pipe failed"; return false; } // Fork the current process: // - Child process is used to start test-platform // - Parent process is killed in order to turn its child into a daemon pid_t pid = fork(); if (pid < 0) { strError = "fork failed!"; return false; } else if (pid == 0) { // Child process : starts test-platform and notify the parent if it succeeds. // Close read side of the pipe close(pipefd[0]); // Init semaphore sem_t sem; sem_init(&sem, false, 0); // Create param mgr CTestPlatform testPlatform(filePath, portNumber, sem); // Message to send to parent process bool loadSuccess = testPlatform.load(strError); if (!loadSuccess) { cerr << strError << endl; // Notify parent of failure; notifyParent(pipefd[1], false); } else { // Notify parent of success notifyParent(pipefd[1], true); // Block here sem_wait(&sem); } sem_destroy(&sem); return loadSuccess; } else { // Parent process : need to kill it once the child notifies the successs/failure to start // test-platform (this status is used as exit value of the program). // Close write side of the pipe close(pipefd[1]); // Message received from the child process bool msgFromChild = false; if (not utility::fullRead(pipefd[0], &msgFromChild, sizeof(msgFromChild))) { strError = "Read pipe failed"; return false; } // return success/failure in exit status return msgFromChild; } } static void showUsage() { cerr << "test-platform [-dh] [port number, default " << iDefaultPortNumber << "]" << endl; } static void showInvalidUsage() { cerr << "Invalid arguments: "; showUsage(); } static void showHelp() { showUsage(); cerr << " must be a valid .xml file, oftenly ParameterFrameworkConfiguration.xml" << endl; cerr << "Arguments:" << endl << " -d starts as a deamon" << endl << " -h display this help and exit" << endl; } int main(int argc, char *argv[]) { // Option found by call to getopt() int opt; // Port number to be used by test-platform int portNumber; // Daemon flag bool isDaemon = false; // Index of the argument in the arguments list provided int indexFilePath = 1; // Handle the -d option while ((opt = getopt(argc, argv, "dh")) != -1) { switch (opt) { case 'd': isDaemon = true; indexFilePath = 2; break; case 'h': showHelp(); return 0; default: showInvalidUsage(); return -1; } } // Check the number of arguments if ((argc < indexFilePath + 1) || (argc > indexFilePath + 2)) { showInvalidUsage(); return -1; } char *filePath = argv[indexFilePath]; portNumber = argc > indexFilePath + 1 ? atoi(argv[indexFilePath + 1]) : iDefaultPortNumber; // Choose either blocking or daemon test-platform bool startError; string strError; if (isDaemon) { startError = startDaemonTestPlatform(filePath, portNumber, strError); } else { startError = startBlockingTestPlatform(filePath, portNumber, strError); } if (!startError) { cerr << "Test-platform error:" << strError.c_str() << endl; return -1; } return 0; }