diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-21 19:27:54 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-21 19:27:54 +0200 |
commit | aa09d40fdcaf9abfe750929c5fe3b19ac1cef0cb (patch) | |
tree | 9b3fb66246e6993ada10922ef249cc0ee43d215e | |
parent | 60a0355316954c96febd7bcd46862a4145a800cd (diff) | |
download | abrt-aa09d40fdcaf9abfe750929c5fe3b19ac1cef0cb.tar.gz abrt-aa09d40fdcaf9abfe750929c5fe3b19ac1cef0cb.tar.xz abrt-aa09d40fdcaf9abfe750929c5fe3b19ac1cef0cb.zip |
move most of CCrashWatcher's init/deinit into daemon's main()
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | inc/abrtlib.h | 3 | ||||
-rw-r--r-- | lib/Utils/xfuncs.cpp | 38 | ||||
-rw-r--r-- | src/Daemon/CrashWatcher.cpp | 71 | ||||
-rw-r--r-- | src/Daemon/CrashWatcher.h | 35 | ||||
-rw-r--r-- | src/Daemon/Daemon.cpp | 200 |
5 files changed, 176 insertions, 171 deletions
diff --git a/inc/abrtlib.h b/inc/abrtlib.h index 5721c6fa..5cde2cb9 100644 --- a/inc/abrtlib.h +++ b/inc/abrtlib.h @@ -108,6 +108,9 @@ void xmove_fd(int from, int to); char* xasprintf(const char *format, ...); std::string ssprintf(const char *format, ...); +int xopen(const char *pathname, int flags); +int xopen3(const char *pathname, int flags, int mode); + /* copyfd_XX print read/write errors and return -1 if they occur */ off_t copyfd_eof(int src_fd, int dst_fd); off_t copyfd_size(int src_fd, int dst_fd, off_t size); diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp index c8aee376..cc147204 100644 --- a/lib/Utils/xfuncs.cpp +++ b/lib/Utils/xfuncs.cpp @@ -252,3 +252,41 @@ std::string get_home_dir(int uid) struct passwd* pw = getpwuid(uid); return pw ? pw->pw_dir : ""; } + +// Die if we can't open a file and return a fd +int xopen3(const char *pathname, int flags, int mode) +{ + int ret; + + ret = open(pathname, flags, mode); + if (ret < 0) { + perror_msg_and_die("can't open '%s'", pathname); + } + return ret; +} + +// Die if we can't open an existing file and return a fd +int xopen(const char *pathname, int flags) +{ + return xopen3(pathname, flags, 0666); +} + +#if 0 //UNUSED +// Warn if we can't open a file and return a fd. +int open3_or_warn(const char *pathname, int flags, int mode) +{ + int ret; + + ret = open(pathname, flags, mode); + if (ret < 0) { + perror_msg("can't open '%s'", pathname); + } + return ret; +} + +// Warn if we can't open a file and return a fd. +int open_or_warn(const char *pathname, int flags) +{ + return open3_or_warn(pathname, flags, 0666); +} +#endif diff --git a/src/Daemon/CrashWatcher.cpp b/src/Daemon/CrashWatcher.cpp index 750d32a6..88868758 100644 --- a/src/Daemon/CrashWatcher.cpp +++ b/src/Daemon/CrashWatcher.cpp @@ -43,79 +43,13 @@ void CCrashWatcher::Debug(const std::string& pMessage, const std::string& pDest) std::cout << "Debug: " + pMessage << std::endl; } -CCrashWatcher::CCrashWatcher(const std::string& pPath) +CCrashWatcher::CCrashWatcher() { g_cw = this; - - int watch = 0; - m_sTarget = pPath; - - // TODO: initialize object according parameters -w -d - // status has to be always created. - m_pCommLayer = NULL; - comm_layer_inner_init(this); - - m_pSettings = new CSettings(); - m_pSettings->LoadSettings(std::string(CONF_DIR) + "/abrt.conf"); - - m_pMainloop = g_main_loop_new(NULL,FALSE); - m_pMW = new CMiddleWare(PLUGINS_CONF_DIR,PLUGINS_LIB_DIR); - if (pthread_mutex_init(&m_pJobsMutex, NULL) != 0) - { - throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Can't init mutex!"); - } - try - { - SetUpMW(); - SetUpCron(); - FindNewDumps(pPath); -#ifdef ENABLE_DBUS - m_pCommLayer = new CCommLayerServerDBus(); -#elif ENABLE_SOCKET - m_pCommLayer = new CCommLayerServerSocket(); -#endif -// m_pCommLayer = new CCommLayerServerDBus(); -// m_pCommLayer = new CCommLayerServerSocket(); - m_pCommLayer->Attach(this); - - if ((m_nFd = inotify_init()) == -1) - { - throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Init Failed"); - } - if ((watch = inotify_add_watch(m_nFd, pPath.c_str(), IN_CREATE)) == -1) - { - throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Add watch failed:" + pPath); - } - m_pGio = g_io_channel_unix_new(m_nFd); - } - catch (...) - { - /* This restores /proc/sys/kernel/core_pattern, among other things */ - delete m_pMW; - //too? delete m_pCommLayer; - throw; - } } CCrashWatcher::~CCrashWatcher() { - //delete dispatcher, connection, etc.. - //m_pConn->disconnect(); - - g_io_channel_unref(m_pGio); - g_main_loop_unref(m_pMainloop); - - delete m_pCommLayer; - delete m_pMW; - delete m_pSettings; - if (pthread_mutex_destroy(&m_pJobsMutex) != 0) - { - throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Can't destroy mutex!"); - } - /* delete pid file */ - unlink(VAR_RUN_PIDFILE); - /* delete lock file */ - unlink(VAR_RUN_LOCK_FILE); } vector_crash_infos_t CCrashWatcher::GetCrashInfos(const std::string &pUID) @@ -348,6 +282,9 @@ map_plugin_settings_t CCrashWatcher::GetPluginSettings(const std::string& pName, } Warning(e.what()); } + // TODO: is it right? I added it just to disable a warning... + // but maybe returning empty map is wrong here? + return vector_map_string_string_t(); } void CCrashWatcher::RegisterPlugin(const std::string& pName) diff --git a/src/Daemon/CrashWatcher.h b/src/Daemon/CrashWatcher.h index 8fe7fb34..4494dfbe 100644 --- a/src/Daemon/CrashWatcher.h +++ b/src/Daemon/CrashWatcher.h @@ -55,8 +55,7 @@ class CCrashWatcher { public: - //CCrashWatcher(const std::string& pPath,DBus::Connection &connection); - CCrashWatcher(const std::string& pPath); + CCrashWatcher(); virtual ~CCrashWatcher(); public: @@ -84,37 +83,19 @@ class CCrashWatcher }; +/* used only for ->Debug(), ->Warning() etc calls */ extern CCrashWatcher *g_cw; -extern int m_nFd; -extern GIOChannel* m_pGio; -extern GMainLoop *m_pMainloop; -extern std::string m_sTarget; -extern CMiddleWare *m_pMW; +/* conduit for these messages */ extern CCommLayerServer *m_pCommLayer; -extern CSettings *m_pSettings; -/** + +extern CMiddleWare *m_pMW; + +/* * Map to cache the results from CreateReport_t * <UID, <UUID, result>> */ extern std::map<const std::string, std::map <int, map_crash_report_t > > m_pending_jobs; -/** -* mutex to protect m_pending_jobs from being accesed by multiple threads at the same time -*/ +/* mutex to protect m_pending_jobs */ extern pthread_mutex_t m_pJobsMutex; - -//extern gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointer data); -//extern void *create_report(void *arg); -//extern gboolean cron_activation_periodic_cb(gpointer data); -//extern gboolean cron_activation_one_cb(gpointer data); -//extern gboolean cron_activation_reshedule_cb(gpointer data); -//extern void cron_delete_callback_data_cb(gpointer data); -//extern void CreatePidFile(); -//extern void Lock(); -extern void SetUpMW(); -extern void SetUpCron(); -/* finds dumps created when daemon wasn't running */ -// FIXME: how to catch abrt itself without this? -extern void FindNewDumps(const std::string& pPath); - #endif /*CRASHWATCHER_H_*/ diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 9dfcdf59..669d1750 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -48,25 +48,20 @@ typedef struct cron_callback_data_t static uint8_t sig_caught; /* = 0 */ +static int m_nFd; +static GIOChannel* m_pGio; +static GMainLoop* m_pMainloop; +static CSettings* m_pSettings; CCrashWatcher *g_cw; -int m_nFd; -GIOChannel* m_pGio; -GMainLoop *m_pMainloop; -std::string m_sTarget; -CMiddleWare *m_pMW; CCommLayerServer *m_pCommLayer; -/*FIXME not needed */ -//DBus::Connection *m_pConn; -CSettings *m_pSettings; -/** +CMiddleWare *m_pMW; +/* * Map to cache the results from CreateReport_t * <UID, <UUID, result>> */ std::map<const std::string, std::map <int, map_crash_report_t > > m_pending_jobs; -/** -* mutex to protect m_pending_jobs from being accesed by multiple threads at the same time -*/ +/* mutex to protect m_pending_jobs */ pthread_mutex_t m_pJobsMutex; @@ -127,7 +122,7 @@ static gboolean cron_activation_periodic_cb(gpointer data) { cron_callback_data_t* cronPeriodicCallbackData = static_cast<cron_callback_data_t*>(data); g_cw->Debug("Activating plugin: " + cronPeriodicCallbackData->m_sPluginName); - m_pMW->RunAction(m_sTarget, + m_pMW->RunAction(DEBUG_DUMPS_DIR, cronPeriodicCallbackData->m_sPluginName, cronPeriodicCallbackData->m_sPluginArgs); return TRUE; @@ -136,7 +131,7 @@ static gboolean cron_activation_one_cb(gpointer data) { cron_callback_data_t* cronOneCallbackData = static_cast<cron_callback_data_t*>(data); g_cw->Debug("Activating plugin: " + cronOneCallbackData->m_sPluginName); - m_pMW->RunAction(m_sTarget, + m_pMW->RunAction(DEBUG_DUMPS_DIR, cronOneCallbackData->m_sPluginName, cronOneCallbackData->m_sPluginArgs); return FALSE; @@ -156,7 +151,7 @@ static gboolean cron_activation_reshedule_cb(gpointer data) return FALSE; } -/*static*/ void SetUpMW() +static void SetUpMW() { m_pMW->SetOpenGPGCheck(m_pSettings->GetOpenGPGCheck()); m_pMW->SetDatabase(m_pSettings->GetDatabase()); @@ -197,7 +192,7 @@ static gboolean cron_activation_reshedule_cb(gpointer data) } } -/*static*/ void SetUpCron() +static void SetUpCron() { CSettings::map_cron_t cron = m_pSettings->GetCron(); CSettings::map_cron_t::iterator it_c; @@ -290,7 +285,7 @@ static gboolean cron_activation_reshedule_cb(gpointer data) } } -/*static*/ void FindNewDumps(const std::string& pPath) +static void FindNewDumps(const std::string& pPath) { g_cw->Debug("Scanning for unsaved entries..."); struct dirent *ep; @@ -540,68 +535,84 @@ static gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointe int main(int argc, char** argv) { - int daemonize = 1; + int daemonize = 0; - /* signal handlers */ signal(SIGTERM, handle_fatal_signal); signal(SIGINT, handle_fatal_signal); - try + /* Daemonize unless -d */ + if (!argv[1] || strcmp(argv[1], "-d") != 0) { - if (argv[1]) + daemonize = 1; + + /* Open stdin to /dev/null. We do it before forking + * in order to emit useful exitcode to the parent + * if open fails */ + close(STDIN_FILENO); + xopen("/dev/null", O_RDWR); + /* forking to background */ + pid_t pid = fork(); + if (pid < 0) { - if (strcmp(argv[1], "-d") == 0) - { - daemonize = 0; - } + perror_msg_and_die("can't fork"); } - if (daemonize) + if (pid > 0) { - /* Open stdin to /dev/null. We do it before forking - * in order to emit useful exitcode to the parent - * if open fails */ - close(STDIN_FILENO); - if (open("/dev/null", O_RDWR)) - { - throw CABRTException(EXCEP_FATAL, "Can't open /dev/null"); - } - /* forking to background */ - pid_t pid = fork(); - if (pid < 0) + /* Parent */ + /* Wait for child to notify us via SIGTERM that it feels ok */ + int i = 20; /* 2 sec */ + while (sig_caught == 0 && --i) { - throw CABRTException(EXCEP_FATAL, "fork error"); + usleep(100 * 1000); } - if (pid > 0) - { - /* Parent */ - /* Wait for child to notify us via SIGTERM that it feels ok */ - int i = 20; /* 2 sec */ - while (sig_caught == 0 && --i) - { - usleep(100 * 1000); - } - _exit(sig_caught != SIGTERM); /* TERM:ok(0), else:bad(1) */ - } - /* Child (daemon) continues */ - pid_t sid = setsid(); - if(sid == -1) - { - throw CABRTException(EXCEP_FATAL, "CCrashWatcher::Daemonize(): setsid failed"); - } - /* We must not leave fds 0,1,2 closed. - * Otherwise fprintf(stderr) dumps messages into random fds, etc. */ - close(STDOUT_FILENO); - close(STDERR_FILENO); - xdup(0); - xdup(0); + _exit(sig_caught != SIGTERM); /* TERM:ok(0), else:bad(1) */ } + /* Child (daemon) continues */ + setsid(); /* never fails */ + /* We must not leave fds 0,1,2 closed. + * Otherwise fprintf(stderr) dumps messages into random fds, etc. */ + close(STDOUT_FILENO); + close(STDERR_FILENO); + xdup(0); + xdup(0); + } - CCrashWatcher watcher(DEBUG_DUMPS_DIR); - watcher.Debug("Running..."); - Lock(); - CreatePidFile(); + CCrashWatcher watcher; + /* Initialization */ + try + { + pthread_mutex_init(&m_pJobsMutex, NULL); /* never fails */ + /* DBus init - we want it early so that errors are reported */ + comm_layer_inner_init(&watcher); + /* Watching DEBUG_DUMPS_DIR for new files... */ + errno = 0; + m_nFd = inotify_init(); + if (m_nFd == -1) + perror_msg_and_die("inotify_init failed"); + if (inotify_add_watch(m_nFd, DEBUG_DUMPS_DIR, IN_CREATE) == -1) + perror_msg_and_die("inotify_add_watch failed on '%s'", DEBUG_DUMPS_DIR); + /* (comment here) */ + m_pSettings = new CSettings(); + m_pSettings->LoadSettings(std::string(CONF_DIR) + "/abrt.conf"); + /* (comment here) */ + m_pMainloop = g_main_loop_new(NULL, FALSE); + /* (comment here) */ + m_pMW = new CMiddleWare(PLUGINS_CONF_DIR, PLUGINS_LIB_DIR); + SetUpMW(); + SetUpCron(); + FindNewDumps(DEBUG_DUMPS_DIR); + /* (comment here) */ +#ifdef ENABLE_DBUS + m_pCommLayer = new CCommLayerServerDBus(); +#elif ENABLE_SOCKET + m_pCommLayer = new CCommLayerServerSocket(); +#endif + m_pCommLayer->Attach(&watcher); + /* (comment here) */ + m_pGio = g_io_channel_unix_new(m_nFd); g_io_add_watch(m_pGio, G_IO_IN, handle_event_cb, NULL); + /* Add an event source which waits for INT/TERM signal */ GSourceFuncs waitsignal_funcs; memset(&waitsignal_funcs, 0, sizeof(waitsignal_funcs)); waitsignal_funcs.prepare = waitsignal_prepare; @@ -610,30 +621,65 @@ int main(int argc, char** argv) /*waitsignal_funcs.finalize = NULL; - already done */ GSource *waitsignal_src = (GSource*) g_source_new(&waitsignal_funcs, sizeof(*waitsignal_src)); g_source_attach(waitsignal_src, g_main_context_default()); - - /* Let parent know we initialized ok */ - if (daemonize) + /* Mark the territory */ + Lock(); + CreatePidFile(); + } + catch (...) + { + /* Initialization error. Clean up, in reverse order */ + unlink(VAR_RUN_PIDFILE); + unlink(VAR_RUN_LOCK_FILE); + g_io_channel_unref(m_pGio); + delete m_pCommLayer; + /* This restores /proc/sys/kernel/core_pattern, among other things: */ + delete m_pMW; + g_main_loop_unref(m_pMainloop); + delete m_pSettings; + if (pthread_mutex_destroy(&m_pJobsMutex) != 0) { - kill(getppid(), SIGTERM); + error_msg("threading error: job mutex locked"); } + /* Inform parent that initialization failed */ + if (daemonize) + kill(getppid(), SIGINT); + error_msg_and_die("error while initializing daemon, exiting"); + } - /* Enter the event loop */ - g_main_run(m_pMainloop); + /* Inform parent that we initialized ok */ + if (daemonize) + kill(getppid(), SIGTERM); + + /* Enter the event loop */ + try + { + watcher.Debug("Running..."); + g_main_run(m_pMainloop); } catch (CABRTException& e) { - std::cerr << "Cannot create daemon: " << e.what() << std::endl; + error_msg("error: %s", e.what().c_str()); } catch (std::exception& e) { - std::cerr << "Cannot create daemon: " << e.what() << std::endl; + error_msg("error: %s", e.what()); } - /* Take care to emit correct exit status */ - if (sig_caught) { + /* Error or INT/TERM. Clean up, in reverse order */ + unlink(VAR_RUN_PIDFILE); + unlink(VAR_RUN_LOCK_FILE); + g_io_channel_unref(m_pGio); + delete m_pCommLayer; + /* This restores /proc/sys/kernel/core_pattern, among other things: */ + delete m_pMW; + g_main_loop_unref(m_pMainloop); + delete m_pSettings; + + /* Exiting */ + if (sig_caught) + { signal(sig_caught, SIG_DFL); raise(sig_caught); } - /* I think we never end up here */ - return 0; + return 1; } |