summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-08-21 19:27:54 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-08-21 19:27:54 +0200
commitaa09d40fdcaf9abfe750929c5fe3b19ac1cef0cb (patch)
tree9b3fb66246e6993ada10922ef249cc0ee43d215e
parent60a0355316954c96febd7bcd46862a4145a800cd (diff)
downloadabrt-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.h3
-rw-r--r--lib/Utils/xfuncs.cpp38
-rw-r--r--src/Daemon/CrashWatcher.cpp71
-rw-r--r--src/Daemon/CrashWatcher.h35
-rw-r--r--src/Daemon/Daemon.cpp200
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;
}