diff options
Diffstat (limited to 'drivers/gator/daemon/main.cpp')
-rw-r--r-- | drivers/gator/daemon/main.cpp | 306 |
1 files changed, 0 insertions, 306 deletions
diff --git a/drivers/gator/daemon/main.cpp b/drivers/gator/daemon/main.cpp deleted file mode 100644 index 51237cbcf75..00000000000 --- a/drivers/gator/daemon/main.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Copyright (C) ARM Limited 2010-2012. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <stdint.h> -#include <stdlib.h> -#include <signal.h> -#include <ctype.h> -#include <sys/wait.h> -#include <unistd.h> -#include <sys/syscall.h> -#include <sys/prctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mount.h> -#include "Child.h" -#include "SessionData.h" -#include "OlySocket.h" -#include "Logging.h" -#include "OlyUtility.h" - -#define DEBUG false - -extern Child* child; -extern void handleException(); -int shutdownFilesystem(); -static pthread_mutex_t numSessions_mutex; -static int numSessions = 0; -static OlySocket* socket = NULL; -static bool driverRunningAtStart = false; -static bool driverMountedAtStart = false; - -struct cmdline_t { - int port; - char* sessionXML; -}; - -void cleanUp() { - if (shutdownFilesystem() == -1) { - logg->logMessage("Error shutting down gator filesystem"); - } - delete socket; - delete util; - delete logg; -} - -// CTRL C Signal Handler -void handler(int signum) { - logg->logMessage("Received signal %d, gator daemon exiting", signum); - - // Case 1: both child and parent receive the signal - if (numSessions > 0) { - // Arbitrary sleep of 1 second to give time for the child to exit; - // if something bad happens, continue the shutdown process regardless - sleep(1); - } - - // Case 2: only the parent received the signal - if (numSessions > 0) { - // Kill child threads - the first signal exits gracefully - logg->logMessage("Killing process group as %d child was running when signal was received", numSessions); - kill(0, SIGINT); - - // Give time for the child to exit - sleep(1); - - if (numSessions > 0) { - // The second signal force kills the child - logg->logMessage("Force kill the child"); - kill(0, SIGINT); - // Again, sleep for 1 second - sleep(1); - - if (numSessions > 0) { - // Something bad has really happened; the child is not exiting and therefore may hold the /dev/gator resource open - printf("Unable to kill the gatord child process, thus gator.ko may still be loaded.\n"); - } - } - } - - cleanUp(); - exit(0); -} - -// Child exit Signal Handler -void child_exit(int signum) { - int status; - int pid = wait(&status); - if (pid != -1) { - pthread_mutex_lock(&numSessions_mutex); - numSessions--; - pthread_mutex_unlock(&numSessions_mutex); - logg->logMessage("Child process %d exited with status %d", pid, status); - } -} - -// retval: -1 = failure; 0 = was already mounted; 1 = successfully mounted -int mountGatorFS() { - // If already mounted, - if (access("/dev/gator/buffer", F_OK) == 0) - return 0; - - // else, mount the filesystem - mkdir("/dev/gator", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (mount("nodev", "/dev/gator", "gatorfs", 0, NULL) != 0) - return -1; - else - return 1; -} - -int setupFilesystem() { - int retval; - - // Verify root permissions - uid_t euid = geteuid(); - if (euid) { - logg->logError(__FILE__, __LINE__, "gatord must be launched with root privileges"); - handleException(); - } - - retval = mountGatorFS(); - if (retval == 1) { - logg->logMessage("Driver already running at startup"); - driverRunningAtStart = true; - } else if (retval == 0) { - logg->logMessage("Driver already mounted at startup"); - driverRunningAtStart = driverMountedAtStart = true; - } else { - char command[256]; // arbitrarily large amount - - // Is the driver co-located in the same directory? - if (util->getApplicationFullPath(command, sizeof(command)) != 0) { // allow some buffer space - logg->logMessage("Unable to determine the full path of gatord, the cwd will be used"); - } - strcat(command, "gator.ko"); - if (access(command, F_OK) == -1) { - logg->logError(__FILE__, __LINE__, "Unable to locate gator.ko driver:\n >>> gator.ko should be co-located with gatord in the same directory\n >>> OR insmod gator.ko prior to launching gatord"); - handleException(); - } - - // Load driver - strcpy(command, "insmod "); - util->getApplicationFullPath(&command[7], sizeof(command) - 64); // allow some buffer space - strcat(command, "gator.ko >/dev/null 2>&1"); - - if (system(command) != 0) { - logg->logMessage("Unable to load gator.ko driver with command: %s", command); - logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details"); - handleException(); - } - - if (mountGatorFS() == -1) { - logg->logError(__FILE__, __LINE__, "Unable to mount the gator filesystem needed for profiling."); - handleException(); - } - } - - return 0; -} - -int shutdownFilesystem() { - if (driverMountedAtStart == false) - umount("/dev/gator"); - if (driverRunningAtStart == false) - if (system("rmmod gator >/dev/null 2>&1") != 0) - return -1; - - return 0; // success -} - -struct cmdline_t parseCommandLine(int argc, char** argv) { - struct cmdline_t cmdline; - cmdline.port = 8080; - cmdline.sessionXML = NULL; - int c; - - while ((c = getopt (argc, argv, "hvp:s:c:")) != -1) { - switch(c) { - case 'p': - cmdline.port = strtol(optarg, NULL, 10); - break; - case 's': - cmdline.sessionXML = optarg; - break; - case 'c': - gSessionData->configurationXMLPath = optarg; - break; - case 'h': - case '?': - logg->logError(__FILE__, __LINE__, - "Streamline gatord version %d. All parameters are optional:\n" - "-p port_number\tport upon which the server listens; default is 8080\n" - "-s session_xml\tpath and filename of a session xml used for local capture\n" - "-c config_xml\tpath and filename of the configuration.xml to use\n" - "-v\t\tversion information\n" - "-h\t\tthis help page\n", PROTOCOL_VERSION); - handleException(); - break; - case 'v': - logg->logError(__FILE__, __LINE__, "Streamline gatord version %d", PROTOCOL_VERSION); - handleException(); - break; - } - } - - // Error checking - if (cmdline.port != 8080 && cmdline.sessionXML != NULL) { - logg->logError(__FILE__, __LINE__, "Only a port or a session xml can be specified, not both"); - handleException(); - } - - if (optind < argc) { - logg->logError(__FILE__, __LINE__, "Unknown argument: %s. Use '-h' for help.", argv[optind]); - handleException(); - } - - return cmdline; -} - -// Gator data flow: collector -> collector fifo -> sender -int main(int argc, char** argv, char *envp[]) { - gSessionData = new SessionData(); // Global data class - logg = new Logging(DEBUG); // Set up global thread-safe logging - util = new OlyUtility(); // Set up global utility class - - prctl(PR_SET_NAME, (unsigned int)&"gatord-main", 0, 0, 0); - pthread_mutex_init(&numSessions_mutex, NULL); - - signal(SIGINT, handler); - signal(SIGTERM, handler); - signal(SIGABRT, handler); - - // Set to high priority - if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), -19) == -1) - logg->logMessage("setpriority() failed"); - - // Initialize session data - gSessionData->initialize(); - - // Parse the command line parameters - struct cmdline_t cmdline = parseCommandLine(argc, argv); - - // Call before setting up the SIGCHLD handler, as system() spawns child processes - setupFilesystem(); - - // Handle child exit codes - signal(SIGCHLD, child_exit); - - // Ignore the SIGPIPE signal so that any send to a broken socket will return an error code instead of asserting a signal - // Handling the error at the send function call is much easier than trying to do anything intelligent in the sig handler - signal(SIGPIPE, SIG_IGN); - - // If the command line argument is a session xml file, no need to open a socket - if (cmdline.sessionXML) { - child = new Child(cmdline.sessionXML); - child->run(); - delete child; - } else { - socket = new OlySocket(cmdline.port, true); - // Forever loop, can be exited via a signal or exception - while (1) { - logg->logMessage("Waiting on connection..."); - socket->acceptConnection(); - - int pid = fork(); - if (pid < 0) { - // Error - logg->logError(__FILE__, __LINE__, "Fork process failed. Please power cycle the target device if this error persists."); - } else if (pid == 0) { - // Child - socket->closeServerSocket(); - child = new Child(socket, numSessions + 1); - child->run(); - delete child; - exit(0); - } else { - // Parent - socket->closeSocket(); - - pthread_mutex_lock(&numSessions_mutex); - numSessions++; - pthread_mutex_unlock(&numSessions_mutex); - - // Maximum number of connections is 2 - int wait = 0; - while (numSessions > 1) { - // Throttle until one of the children exits before continuing to accept another socket connection - logg->logMessage("%d sessions active!", numSessions); - if (wait++ >= 10) { // Wait no more than 10 seconds - // Kill last created child - kill(pid, SIGALRM); - break; - } - sleep(1); - } - } - } - } - - cleanUp(); - return 0; -} |