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>
This commit is contained in:
Sage Weil 2014-09-12 17:18:01 -07:00
parent e3fe18aabe
commit a8c943a0e4
4 changed files with 47 additions and 1 deletions

View File

@ -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::

View File

@ -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();
};
}

View File

@ -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(), ".*");
}

View File

@ -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)
{