From 6221ea763d51f6ae2ac43c6b0b10d3b1ebe817ff Mon Sep 17 00:00:00 2001 From: Jussi Lind Date: Tue, 26 Apr 2011 12:00:22 +0300 Subject: [PATCH] Changes: Error handling improvements. Details: Throw std::runtime_error() instead of logErrorAndDie(). RevBy: Alexey Shilov --- src/launcherlib/booster.cpp | 18 +++++++++----- src/launcherlib/connection.cpp | 5 ++-- src/launcherlib/daemon.cpp | 39 ++++++++++------------------- src/launcherlib/logger.cpp | 11 --------- src/launcherlib/logger.h | 9 ------- src/launcherlib/main.cpp | 41 ++++++++++++++++++++----------- src/launcherlib/socketmanager.cpp | 35 ++++++++++++++++++++++---- 7 files changed, 83 insertions(+), 75 deletions(-) diff --git a/src/launcherlib/booster.cpp b/src/launcherlib/booster.cpp index 17ca9be..24b826d 100644 --- a/src/launcherlib/booster.cpp +++ b/src/launcherlib/booster.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef Q_WS_X11 #include @@ -124,9 +125,8 @@ void Booster::initialize(int initialArgc, char ** initialArgv, int newBoosterLau // Wait and read commands from the invoker Logger::logDebug("Booster: Wait for message from invoker"); - if (!receiveDataFromInvoker(socketFd)) { - Logger::logErrorAndDie(EXIT_FAILURE, "Booster: Couldn't read command\n"); - } + if (!receiveDataFromInvoker(socketFd)) + throw std::runtime_error("Booster: Couldn't read command\n"); // Send parent process a message that it can create a new booster, // send pid of invoker, booster respawn value and invoker socket connection. @@ -462,7 +462,11 @@ void Booster::setEnvironmentBeforeLaunch() if (err < 0) { // Credential setup has failed, abort. - Logger::logErrorAndDie(EXIT_FAILURE, "Booster: Failed to setup credentials for launching application: %d\n", err); + std::string msg("Booster: Failed to setup credentials for launching application: "); + std::stringstream ss; + ss << err; + msg += ss.str(); + throw std::runtime_error(msg); } #endif @@ -545,7 +549,8 @@ void* Booster::loadMain() void * module = dlopen(m_appData->fileName().c_str(), dlopenFlags); if (!module) - Logger::logErrorAndDie(EXIT_FAILURE, "Booster: Loading invoked application failed: '%s'\n", dlerror()); + throw std::runtime_error(std::string("Booster: Loading invoked application failed: '") + + dlerror() + "'\n"); // Find out the address for symbol "main". dlerror() is first used to clear any old error conditions, // then dlsym() is called, and then dlerror() is checked again. This procedure is documented @@ -556,7 +561,8 @@ void* Booster::loadMain() const char * error_s = dlerror(); if (error_s != NULL) - Logger::logErrorAndDie(EXIT_FAILURE, "Booster: Loading symbol 'main' failed: '%s'\n", error_s); + throw std::runtime_error(std::string("Booster: Loading symbol 'main' failed: '") + + error_s + "'\n"); return module; } diff --git a/src/launcherlib/connection.cpp b/src/launcherlib/connection.cpp index 7f8d65e..f0e33ed 100644 --- a/src/launcherlib/connection.cpp +++ b/src/launcherlib/connection.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #if defined (HAVE_CREDS) && ! defined (DISABLE_VERIFICATION) const char * Connection::m_credsStr = "applauncherd-launcher::access"; @@ -57,9 +58,7 @@ Connection::Connection(int socketFd, bool testMode) : m_io[2] = -1; if (!m_testMode && m_curSocket == -1) - { - Logger::logErrorAndDie(EXIT_FAILURE, "Connection: Socket isn't initialized!\n"); - } + throw std::runtime_error("Connection: Socket isn't initialized!\n"); #if defined (HAVE_CREDS) && ! defined (DISABLE_VERIFICATION) diff --git a/src/launcherlib/daemon.cpp b/src/launcherlib/daemon.cpp index b612185..6612eca 100644 --- a/src/launcherlib/daemon.cpp +++ b/src/launcherlib/daemon.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include "coverage.h" @@ -57,7 +58,7 @@ Daemon::Daemon(int & argc, char * argv[]) : } else { - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Daemon already created!\n"); + throw std::runtime_error("Daemon: Daemon already created!\n"); } // Parse arguments @@ -73,12 +74,12 @@ Daemon::Daemon(int & argc, char * argv[]) : if (socketpair(AF_UNIX, SOCK_DGRAM, 0, m_boosterLauncherSocket) == -1) { - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Creating a socket pair for boosters failed!\n"); + throw std::runtime_error("Daemon: Creating a socket pair for boosters failed!\n"); } if (pipe(m_sigPipeFd) == -1) { - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Creating a pipe for Unix signals failed!\n"); + throw std::runtime_error("Daemon: Creating a pipe for Unix signals failed!\n"); } // Daemonize if desired @@ -95,11 +96,11 @@ void Daemon::consoleQuiet() close(2); if (open("/dev/null", O_RDONLY) < 0) - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Failed to open /dev/null as read-only"); + throw std::runtime_error("Daemon: Failed to open /dev/null as read-only"); int fd = open("/dev/null", O_WRONLY); if ((fd == -1) || (dup(fd) < 0)) - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Failed to open /dev/null as write-only"); + throw std::runtime_error("Daemon: Failed to open /dev/null as write-only"); } Daemon * Daemon::instance() @@ -400,7 +401,7 @@ void Daemon::forkBooster(char type, int sleepTime) pid_t newPid = fork(); if (newPid == -1) - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Forking while invoking"); + throw std::runtime_error("Daemon: Forking while invoking"); if (newPid == 0) /* Child process */ { @@ -470,7 +471,7 @@ void Daemon::forkBooster(char type, int sleepTime) } else { - Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Unknown booster type '%c'\n", type); + throw std::runtime_error(std::string("Daemon: Unknown booster type '") + type + "'"); } } else /* Parent process */ @@ -597,10 +598,7 @@ void Daemon::daemonize() // Fork off the parent process: first fork pid = fork(); if (pid < 0) - { - Logger::logError("Daemon: Unable to fork daemon, code %d (%s)", errno, strerror(errno)); - exit(EXIT_FAILURE); - } + throw std::runtime_error("Daemon: Unable to fork daemon"); // If we got a good PID, then we can exit the parent process. if (pid > 0) @@ -611,10 +609,7 @@ void Daemon::daemonize() // Fork off the parent process: second fork pid = fork(); if (pid < 0) - { - Logger::logError("Daemon: Unable to fork daemon, code %d (%s)", errno, strerror(errno)); - exit(EXIT_FAILURE); - } + throw std::runtime_error("Daemon: Unable to fork daemon"); // If we got a good PID, then we can exit the parent process. if (pid > 0) @@ -624,9 +619,7 @@ void Daemon::daemonize() // Check the lock if(!Daemon::lock()) - { - Logger::logErrorAndDie(EXIT_FAILURE, "%s is already running \n", PROG_NAME_LAUNCHER); - } + throw std::runtime_error(std::string(PROG_NAME_LAUNCHER) + " is already running\n"); // Change the file mode mask umask(0); @@ -636,17 +629,11 @@ void Daemon::daemonize() // Create a new SID for the child process sid = setsid(); if (sid < 0) - { - Logger::logError("Daemon: Unable to create a new session, code %d (%s)", errno, strerror(errno)); - exit(EXIT_FAILURE); - } + throw std::runtime_error("Daemon: Unable to setsid."); // Change the current working directory if ((chdir("/")) < 0) - { - Logger::logError("Daemon: Unable to change directory to %s, code %d (%s)", "/", errno, strerror(errno)); - exit(EXIT_FAILURE); - } + throw std::runtime_error("Daemon: Unable to chdir to '/'"); // Open file descriptors pointing to /dev/null // Redirect standard file descriptors to /dev/null diff --git a/src/launcherlib/logger.cpp b/src/launcherlib/logger.cpp index 36ffec6..cb8b58c 100644 --- a/src/launcherlib/logger.cpp +++ b/src/launcherlib/logger.cpp @@ -96,17 +96,6 @@ void Logger::logError(const char * format, ...) va_end(ap); } -void Logger::logErrorAndDie(int code, const char * format, ...) -{ - va_list(ap); - va_start(ap, format); - writeLog(LOG_ERR, format, ap); - vfprintf(stderr, format, ap); - va_end(ap); - - _exit(code); -} - void Logger::setDebugMode(bool enable) { Logger::m_debugMode = enable; diff --git a/src/launcherlib/logger.h b/src/launcherlib/logger.h index 69b1be6..9f48b46 100644 --- a/src/launcherlib/logger.h +++ b/src/launcherlib/logger.h @@ -79,15 +79,6 @@ public: */ static void logInfo(const char * format, ...); - /*! - * \brief Log an error to the system message logger and exit - * \param format String identical to a printf format string - * \param additionalArgs Depending on the format string, the function may expect a - * sequence of additional arguments, each containing one value to be inserted - * in the format parameter, if any. - */ - static void logErrorAndDie(int code, const char * format, ...); - /*! * \brief Forces Logger to log everything and echo to stdout if set to true. */ diff --git a/src/launcherlib/main.cpp b/src/launcherlib/main.cpp index e0d99b1..f40f36e 100644 --- a/src/launcherlib/main.cpp +++ b/src/launcherlib/main.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #define DECL_EXPORT extern "C" __attribute__ ((__visibility__("default"))) @@ -79,28 +80,38 @@ DECL_EXPORT int main(int argc, char * argv[]) { if(!Daemon::lock()) { - Logger::logErrorAndDie(EXIT_FAILURE, "%s is already running \n", PROG_NAME_LAUNCHER); + Logger::logError("%s is already running \n", PROG_NAME_LAUNCHER); + return EXIT_FAILURE; } } - // Create main daemon instance - Daemon myDaemon(argc, argv); + try + { + // Create main daemon instance + Daemon myDaemon(argc, argv); - // Get fd for signal pipe. - g_sigPipeFd = myDaemon.sigPipeFd(); + // Get fd for signal pipe. + g_sigPipeFd = myDaemon.sigPipeFd(); - // Install signal handlers - signal(SIGCHLD, sigChldHandler); // reap zombies - signal(SIGTERM, sigTermHandler); // exit launcher - signal(SIGUSR1, sigUsr1Handler); // enter normal mode from boot mode - signal(SIGUSR2, sigUsr2Handler); // enter boot mode (same as --boot-mode) - signal(SIGPIPE, sigPipeHandler); // broken invoker's pipe + // Install signal handlers + signal(SIGCHLD, sigChldHandler); // reap zombies + signal(SIGTERM, sigTermHandler); // exit launcher + signal(SIGUSR1, sigUsr1Handler); // enter normal mode from boot mode + signal(SIGUSR2, sigUsr2Handler); // enter boot mode (same as --boot-mode) + signal(SIGPIPE, sigPipeHandler); // broken invoker's pipe - // Run the main loop - myDaemon.run(); + // Run the main loop + myDaemon.run(); - // Close the log - Logger::closeLog(); + // Close the log + Logger::closeLog(); + } + catch (std::runtime_error & e) + { + Logger::logError(e.what()); + std::cout << e.what() << std::endl; + return EXIT_FAILURE; + } return EXIT_SUCCESS; } diff --git a/src/launcherlib/socketmanager.cpp b/src/launcherlib/socketmanager.cpp index 63a8124..242d176 100644 --- a/src/launcherlib/socketmanager.cpp +++ b/src/launcherlib/socketmanager.cpp @@ -22,9 +22,13 @@ #include #include +#include #include #include #include +#include +#include +#include void SocketManager::initSocket(const string & socketId) { @@ -37,14 +41,23 @@ void SocketManager::initSocket(const string & socketId) // Create a new local socket int socketFd = socket(PF_UNIX, SOCK_STREAM, 0); if (socketFd < 0) - Logger::logErrorAndDie(EXIT_FAILURE, "SocketManager: Failed to open socket\n"); + throw std::runtime_error("SocketManager: Failed to open socket\n"); // TODO: Error if socketId >= maxLen. Also unlink() here may // try to remove a different file than is passed to sun.sa_data. // Remove the previous socket file - if (unlink(socketId.c_str())) - Logger::logError("SocketManager: Failed to unlink existing socket file '%s'", socketId.c_str()); + struct stat sb; + stat(socketId.c_str(), &sb); + if (S_ISSOCK(sb.st_mode)) + { + if (unlink(socketId.c_str()) == -1) + { + std::string msg("SocketManager: Failed to unlink existing socket file '"); + msg += socketId + "': " + strerror(errno); + Logger::logWarning(msg.c_str()); + } + } // Initialize the socket struct struct sockaddr sun; @@ -55,11 +68,23 @@ void SocketManager::initSocket(const string & socketId) // Bind the socket if (bind(socketFd, &sun, sizeof(sun)) < 0) - Logger::logErrorAndDie(EXIT_FAILURE, "SocketManager: Failed to bind to socket (fd=%d)\n", socketFd); + { + std::string msg("SocketManager: Failed to bind to socket (fd="); + std::stringstream ss; + ss << socketFd; + msg += ss.str() + ")"; + throw std::runtime_error(msg); + } // Listen to the socket if (listen(socketFd, 10) < 0) - Logger::logErrorAndDie(EXIT_FAILURE, "SocketManager: Failed to listen to socket (fd=%d)\n", socketFd); + { + std::string msg("SocketManager: Failed to listen to socket (fd="); + std::stringstream ss; + ss << socketFd; + msg += ss.str() + ")"; + throw std::runtime_error(msg); + } // Set permissions chmod(socketId.c_str(), S_IRUSR | S_IWUSR | S_IXUSR |