summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@redhat.com>2014-09-13 02:18:01 +0200
committerSage Weil <sage@redhat.com>2014-09-13 02:18:01 +0200
commita8c943a0e4210aadf96cab4a71e9e7a458e9a422 (patch)
tree80618dc0ee9e97060d1997dcdcb98847c7a4476e
parentglobal/signal_handler: do not log if SEGV originated inside log code (diff)
downloadceph-a8c943a0e4210aadf96cab4a71e9e7a458e9a422.tar.xz
ceph-a8c943a0e4210aadf96cab4a71e9e7a458e9a422.zip
log: add simple test to verify an internal SEGV doesn't hang
Test that the segv injection works. Test that a segv while logging something doesn't hang when the signal handlers are installed. Note that this fails/hangs without the previous fix. Signed-off-by: Sage Weil <sage@redhat.com>
-rw-r--r--src/log/Log.cc11
-rw-r--r--src/log/Log.h5
-rw-r--r--src/log/test.cc22
-rw-r--r--src/test/signals.cc10
4 files changed, 47 insertions, 1 deletions
diff --git a/src/log/Log.cc b/src/log/Log.cc
index 8da77ef8b77..046774dfce8 100644
--- a/src/log/Log.cc
+++ b/src/log/Log.cc
@@ -45,7 +45,8 @@ Log::Log(SubsystemMap *s)
m_stderr_log(1), m_stderr_crash(-1),
m_stop(false),
m_max_new(DEFAULT_MAX_NEW),
- m_max_recent(DEFAULT_MAX_RECENT)
+ m_max_recent(DEFAULT_MAX_RECENT),
+ m_inject_segv(false)
{
int ret;
@@ -145,6 +146,9 @@ void Log::submit_entry(Entry *e)
pthread_mutex_lock(&m_queue_mutex);
m_queue_mutex_holder = pthread_self();
+ if (m_inject_segv)
+ *(int *)(0) = 0xdead;
+
// wait for flush to catch up
while (m_new.m_len > m_max_new)
pthread_cond_wait(&m_cond_loggers, &m_queue_mutex);
@@ -353,5 +357,10 @@ bool Log::is_inside_log_lock()
pthread_self() == m_flush_mutex_holder;
}
+void Log::inject_segv()
+{
+ m_inject_segv = true;
+}
+
} // ceph::log::
} // ceph::
diff --git a/src/log/Log.h b/src/log/Log.h
index b77be87e82e..04cadd726f6 100644
--- a/src/log/Log.h
+++ b/src/log/Log.h
@@ -42,6 +42,8 @@ class Log : private Thread
int m_max_new, m_max_recent;
+ bool m_inject_segv;
+
void *entry();
void _flush(EntryQueue *q, EntryQueue *requeue, bool crash);
@@ -74,6 +76,9 @@ public:
/// true if the log lock is held by our thread
bool is_inside_log_lock();
+
+ /// induce a segv on the next log event
+ void inject_segv();
};
}
diff --git a/src/log/test.cc b/src/log/test.cc
index 85e9ebc01bd..6e4704befde 100644
--- a/src/log/test.cc
+++ b/src/log/test.cc
@@ -187,3 +187,25 @@ TEST(Log, ManyGather)
log.flush();
log.stop();
}
+
+void do_segv()
+{
+ SubsystemMap subs;
+ subs.add(1, "foo", 20, 1);
+ Log log(&subs);
+ log.start();
+ log.set_log_file("/tmp/big");
+ log.reopen_log_file();
+
+ log.inject_segv();
+ Entry *e = new Entry(ceph_clock_now(NULL), pthread_self(), 10, 1);
+ log.submit_entry(e); // this should segv
+
+ log.flush();
+ log.stop();
+}
+
+TEST(Log, InternalSegv)
+{
+ ASSERT_DEATH(do_segv(), ".*");
+}
diff --git a/src/test/signals.cc b/src/test/signals.cc
index 2c7f4d32a0a..2cae0fab8f9 100644
--- a/src/test/signals.cc
+++ b/src/test/signals.cc
@@ -1,6 +1,7 @@
#include "common/config.h"
#include "common/signal.h"
#include "global/signal_handler.h"
+#include "common/debug.h"
#include "test/unit.h"
@@ -9,6 +10,8 @@
#include <stdlib.h>
#include <unistd.h>
+#include "include/assert.h"
+
static volatile sig_atomic_t got_sigusr1 = 0;
static void handle_sigusr1(int signo)
@@ -111,6 +114,13 @@ TEST(SignalHandler, Multiple)
shutdown_async_signal_handler();
}
+TEST(SignalHandler, LogInternal)
+{
+ g_ceph_context->_log->inject_segv();
+ ASSERT_DEATH(derr << "foo" << dendl, ".*");
+}
+
+
/*
TEST(SignalHandler, MultipleBigFd)
{