*
*/
+#include <errno.h>
#include <iostream>
+#include <pthread.h>
#include <sstream>
+#include <time.h>
#include "BackTrace.h"
#include "common/debug.h"
#include "config.h"
#include "include/assert.h"
+static bool dout_trylock(void)
+{
+ time_t cur;
+ time_t end_time = time(NULL);
+ end_time += 10;
+
+ do {
+ int ret = pthread_mutex_trylock(&_dout_lock);
+ if (ret == 0) {
+ // We got the mutex.
+ return true;
+ }
+ else if ((ret == EDEADLK) || (ret == EAGAIN)) {
+ // This thread already owns the mutex.
+ // The assertion happened inside a call to dout()?
+ return false;
+ }
+ else if (ret == EINVAL) {
+ // We can never get the mutex.
+ return false;
+ }
+ // Otherwise, keep trying.
+ usleep(1000);
+ cur = time(NULL);
+ } while (cur < end_time);
+
+ // If 10 seconds go by and we can't get the mutex, just bail.
+ return false;
+}
+
namespace ceph {
void __ceph_assert_fail(const char *assertion, const char *file, int line, const char *func)
{
- // TODO: replace this with a trylock
- DoutLocker _dout_locker;
+ int got_lock = dout_trylock();
char buf[8096];
BackTrace *bt = new BackTrace(1);
"is needed to interpret this.\n");
dout_emergency(oss.str());
+ if (got_lock) {
+ int ret = pthread_mutex_unlock(&_dout_lock);
+ if (ret) {
+ ; // ignored
+ }
+ }
+
throw FailedAssertion(bt);
}
void __ceph_assert_warn(const char *assertion, const char *file,
int line, const char *func)
{
- // TODO: replace this with a trylock
- DoutLocker _dout_locker;
+ int got_lock = dout_trylock();
char buf[8096];
snprintf(buf, sizeof(buf),
"WARNING: assert(%s) at: %s: %d: %s()\n",
assertion, file, line, func);
dout_emergency(buf);
+
+ if (got_lock) {
+ int ret = pthread_mutex_unlock(&_dout_lock);
+ if (ret) {
+ ; // ignored
+ }
+ }
}
}