Changes: Error handling improvements.

Details: Throw std::runtime_error() instead of logErrorAndDie().

RevBy: Alexey Shilov
pull/1/head
Jussi Lind 15 years ago
parent e6456cc718
commit 6221ea763d

@ -34,6 +34,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <stdexcept>
#ifdef Q_WS_X11 #ifdef Q_WS_X11
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -124,9 +125,8 @@ void Booster::initialize(int initialArgc, char ** initialArgv, int newBoosterLau
// Wait and read commands from the invoker // Wait and read commands from the invoker
Logger::logDebug("Booster: Wait for message from invoker"); Logger::logDebug("Booster: Wait for message from invoker");
if (!receiveDataFromInvoker(socketFd)) { if (!receiveDataFromInvoker(socketFd))
Logger::logErrorAndDie(EXIT_FAILURE, "Booster: Couldn't read command\n"); throw std::runtime_error("Booster: Couldn't read command\n");
}
// Send parent process a message that it can create a new booster, // Send parent process a message that it can create a new booster,
// send pid of invoker, booster respawn value and invoker socket connection. // send pid of invoker, booster respawn value and invoker socket connection.
@ -462,7 +462,11 @@ void Booster::setEnvironmentBeforeLaunch()
if (err < 0) if (err < 0)
{ {
// Credential setup has failed, abort. // 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 #endif
@ -545,7 +549,8 @@ void* Booster::loadMain()
void * module = dlopen(m_appData->fileName().c_str(), dlopenFlags); void * module = dlopen(m_appData->fileName().c_str(), dlopenFlags);
if (!module) 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, // 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 // 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(); const char * error_s = dlerror();
if (error_s != NULL) 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; return module;
} }

@ -27,6 +27,7 @@
#include <cstdlib> #include <cstdlib>
#include <cerrno> #include <cerrno>
#include <unistd.h> #include <unistd.h>
#include <stdexcept>
#if defined (HAVE_CREDS) && ! defined (DISABLE_VERIFICATION) #if defined (HAVE_CREDS) && ! defined (DISABLE_VERIFICATION)
const char * Connection::m_credsStr = "applauncherd-launcher::access"; const char * Connection::m_credsStr = "applauncherd-launcher::access";
@ -57,9 +58,7 @@ Connection::Connection(int socketFd, bool testMode) :
m_io[2] = -1; m_io[2] = -1;
if (!m_testMode && m_curSocket == -1) if (!m_testMode && m_curSocket == -1)
{ throw std::runtime_error("Connection: Socket isn't initialized!\n");
Logger::logErrorAndDie(EXIT_FAILURE, "Connection: Socket isn't initialized!\n");
}
#if defined (HAVE_CREDS) && ! defined (DISABLE_VERIFICATION) #if defined (HAVE_CREDS) && ! defined (DISABLE_VERIFICATION)

@ -37,6 +37,7 @@
#include <glob.h> #include <glob.h>
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <stdexcept>
#include "coverage.h" #include "coverage.h"
@ -57,7 +58,7 @@ Daemon::Daemon(int & argc, char * argv[]) :
} }
else else
{ {
Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Daemon already created!\n"); throw std::runtime_error("Daemon: Daemon already created!\n");
} }
// Parse arguments // Parse arguments
@ -73,12 +74,12 @@ Daemon::Daemon(int & argc, char * argv[]) :
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, m_boosterLauncherSocket) == -1) 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) 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 // Daemonize if desired
@ -95,11 +96,11 @@ void Daemon::consoleQuiet()
close(2); close(2);
if (open("/dev/null", O_RDONLY) < 0) 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); int fd = open("/dev/null", O_WRONLY);
if ((fd == -1) || (dup(fd) < 0)) 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() Daemon * Daemon::instance()
@ -400,7 +401,7 @@ void Daemon::forkBooster(char type, int sleepTime)
pid_t newPid = fork(); pid_t newPid = fork();
if (newPid == -1) if (newPid == -1)
Logger::logErrorAndDie(EXIT_FAILURE, "Daemon: Forking while invoking"); throw std::runtime_error("Daemon: Forking while invoking");
if (newPid == 0) /* Child process */ if (newPid == 0) /* Child process */
{ {
@ -470,7 +471,7 @@ void Daemon::forkBooster(char type, int sleepTime)
} }
else 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 */ else /* Parent process */
@ -597,10 +598,7 @@ void Daemon::daemonize()
// Fork off the parent process: first fork // Fork off the parent process: first fork
pid = fork(); pid = fork();
if (pid < 0) if (pid < 0)
{ throw std::runtime_error("Daemon: Unable to fork daemon");
Logger::logError("Daemon: Unable to fork daemon, code %d (%s)", errno, strerror(errno));
exit(EXIT_FAILURE);
}
// If we got a good PID, then we can exit the parent process. // If we got a good PID, then we can exit the parent process.
if (pid > 0) if (pid > 0)
@ -611,10 +609,7 @@ void Daemon::daemonize()
// Fork off the parent process: second fork // Fork off the parent process: second fork
pid = fork(); pid = fork();
if (pid < 0) if (pid < 0)
{ throw std::runtime_error("Daemon: Unable to fork daemon");
Logger::logError("Daemon: Unable to fork daemon, code %d (%s)", errno, strerror(errno));
exit(EXIT_FAILURE);
}
// If we got a good PID, then we can exit the parent process. // If we got a good PID, then we can exit the parent process.
if (pid > 0) if (pid > 0)
@ -624,9 +619,7 @@ void Daemon::daemonize()
// Check the lock // Check the lock
if(!Daemon::lock()) if(!Daemon::lock())
{ throw std::runtime_error(std::string(PROG_NAME_LAUNCHER) + " is already running\n");
Logger::logErrorAndDie(EXIT_FAILURE, "%s is already running \n", PROG_NAME_LAUNCHER);
}
// Change the file mode mask // Change the file mode mask
umask(0); umask(0);
@ -636,17 +629,11 @@ void Daemon::daemonize()
// Create a new SID for the child process // Create a new SID for the child process
sid = setsid(); sid = setsid();
if (sid < 0) if (sid < 0)
{ throw std::runtime_error("Daemon: Unable to setsid.");
Logger::logError("Daemon: Unable to create a new session, code %d (%s)", errno, strerror(errno));
exit(EXIT_FAILURE);
}
// Change the current working directory // Change the current working directory
if ((chdir("/")) < 0) if ((chdir("/")) < 0)
{ throw std::runtime_error("Daemon: Unable to chdir to '/'");
Logger::logError("Daemon: Unable to change directory to %s, code %d (%s)", "/", errno, strerror(errno));
exit(EXIT_FAILURE);
}
// Open file descriptors pointing to /dev/null // Open file descriptors pointing to /dev/null
// Redirect standard file descriptors to /dev/null // Redirect standard file descriptors to /dev/null

@ -96,17 +96,6 @@ void Logger::logError(const char * format, ...)
va_end(ap); 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) void Logger::setDebugMode(bool enable)
{ {
Logger::m_debugMode = enable; Logger::m_debugMode = enable;

@ -79,15 +79,6 @@ public:
*/ */
static void logInfo(const char * format, ...); 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. * \brief Forces Logger to log everything and echo to stdout if set to true.
*/ */

@ -28,6 +28,7 @@
#include <signal.h> #include <signal.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/file.h> #include <sys/file.h>
#include <stdexcept>
#define DECL_EXPORT extern "C" __attribute__ ((__visibility__("default"))) #define DECL_EXPORT extern "C" __attribute__ ((__visibility__("default")))
@ -79,28 +80,38 @@ DECL_EXPORT int main(int argc, char * argv[])
{ {
if(!Daemon::lock()) 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 try
Daemon myDaemon(argc, argv); {
// Create main daemon instance
Daemon myDaemon(argc, argv);
// Get fd for signal pipe. // Get fd for signal pipe.
g_sigPipeFd = myDaemon.sigPipeFd(); g_sigPipeFd = myDaemon.sigPipeFd();
// Install signal handlers // Install signal handlers
signal(SIGCHLD, sigChldHandler); // reap zombies signal(SIGCHLD, sigChldHandler); // reap zombies
signal(SIGTERM, sigTermHandler); // exit launcher signal(SIGTERM, sigTermHandler); // exit launcher
signal(SIGUSR1, sigUsr1Handler); // enter normal mode from boot mode signal(SIGUSR1, sigUsr1Handler); // enter normal mode from boot mode
signal(SIGUSR2, sigUsr2Handler); // enter boot mode (same as --boot-mode) signal(SIGUSR2, sigUsr2Handler); // enter boot mode (same as --boot-mode)
signal(SIGPIPE, sigPipeHandler); // broken invoker's pipe signal(SIGPIPE, sigPipeHandler); // broken invoker's pipe
// Run the main loop // Run the main loop
myDaemon.run(); myDaemon.run();
// Close the log // Close the log
Logger::closeLog(); Logger::closeLog();
}
catch (std::runtime_error & e)
{
Logger::logError(e.what());
std::cout << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

@ -22,9 +22,13 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <stdexcept>
#include <errno.h>
#include <sstream>
void SocketManager::initSocket(const string & socketId) void SocketManager::initSocket(const string & socketId)
{ {
@ -37,14 +41,23 @@ void SocketManager::initSocket(const string & socketId)
// Create a new local socket // Create a new local socket
int socketFd = socket(PF_UNIX, SOCK_STREAM, 0); int socketFd = socket(PF_UNIX, SOCK_STREAM, 0);
if (socketFd < 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 // TODO: Error if socketId >= maxLen. Also unlink() here may
// try to remove a different file than is passed to sun.sa_data. // try to remove a different file than is passed to sun.sa_data.
// Remove the previous socket file // Remove the previous socket file
if (unlink(socketId.c_str())) struct stat sb;
Logger::logError("SocketManager: Failed to unlink existing socket file '%s'", socketId.c_str()); 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 // Initialize the socket struct
struct sockaddr sun; struct sockaddr sun;
@ -55,11 +68,23 @@ void SocketManager::initSocket(const string & socketId)
// Bind the socket // Bind the socket
if (bind(socketFd, &sun, sizeof(sun)) < 0) 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 // Listen to the socket
if (listen(socketFd, 10) < 0) 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 // Set permissions
chmod(socketId.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | chmod(socketId.c_str(), S_IRUSR | S_IWUSR | S_IXUSR |

Loading…
Cancel
Save