#undef pthread_cond_wait
#undef pthread_cond_timedwait
+#if defined(DEBUG_THREADS)
+#define log_mutex_error(canlog, ...) \
+ do { \
+ if (canlog) { \
+ ast_log(LOG_ERROR, __VA_ARGS__); \
+ } else { \
+ fprintf(stderr, __VA_ARGS__); \
+ } \
+ } while (0)
+#endif
+
#if defined(DEBUG_THREADS) && defined(HAVE_BKTR)
static void __dump_backtrace(struct ast_bt *bt, int canlog)
{
strings = backtrace_symbols(bt->addresses, bt->num_frames);
for (i = 0; i < bt->num_frames; i++) {
- __ast_mutex_logger("%s\n", strings[i]);
+ log_mutex_error(canlog, "%s\n", strings[i]);
}
ast_std_free(strings);
if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
int canlog = tracking && strcmp(filename, "logger.c");
- __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
filename, lineno, func, mutex_name);
DO_THREAD_CRASH;
return EBUSY;
* linked with libpthread.
* This is not an error condition if the mutex is created on the fly.
*/
- __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
DO_THREAD_CRASH;
res = EINVAL;
pthread_mutex_unlock(&t->mutex);
break;
case EINVAL:
- __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
filename, lineno, func, mutex_name);
break;
case EBUSY:
- __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
filename, lineno, func, mutex_name);
if (lt) {
ast_reentrancy_lock(lt);
- __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: '%s' was locked here.\n",
lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
#ifdef HAVE_BKTR
__dump_backtrace(<->backtrace[ROFFSET], canlog);
#ifdef DEBUG_THREADS
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error destroying mutex %s: %s\n",
filename, lineno, func, mutex_name, strerror(res));
}
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
if (res == EBUSY) {
wait_time = time(NULL) - seconds;
if (wait_time > reported_wait && (wait_time % 5) == 0) {
- __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
+ log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
filename, lineno, func, (int) wait_time, mutex_name);
if (lt) {
ast_reentrancy_lock(lt);
#ifdef HAVE_BKTR
__dump_backtrace(<->backtrace[lt->reentrancy], canlog);
#endif
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
lt->file[ROFFSET], lt->lineno[ROFFSET],
lt->func[ROFFSET], mutex_name);
#ifdef HAVE_BKTR
lt->thread_id[lt->reentrancy] = pthread_self();
lt->reentrancy++;
} else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
ast_reentrancy_unlock(lt);
#endif
}
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error obtaining mutex: %s\n",
filename, lineno, func, strerror(res));
DO_THREAD_CRASH;
}
lt->thread_id[lt->reentrancy] = pthread_self();
lt->reentrancy++;
} else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
ast_reentrancy_unlock(lt);
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
DO_THREAD_CRASH;
return EINVAL;
if (lt) {
ast_reentrancy_lock(lt);
if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
- __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
+ log_mutex_error(canlog, "%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
#ifdef HAVE_BKTR
__dump_backtrace(<->backtrace[ROFFSET], canlog);
}
if (--lt->reentrancy < 0) {
- __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
+ log_mutex_error(canlog, "%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
filename, lineno, func, mutex_name);
lt->reentrancy = 0;
}
#ifdef DEBUG_THREADS
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error releasing mutex: %s\n",
filename, lineno, func, strerror(res));
DO_THREAD_CRASH;
}
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
DO_THREAD_CRASH;
return EINVAL;
if (lt) {
ast_reentrancy_lock(lt);
if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
- __ast_mutex_logger("%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
+ log_mutex_error(canlog, "%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
#ifdef HAVE_BKTR
__dump_backtrace(<->backtrace[ROFFSET], canlog);
#endif
DO_THREAD_CRASH;
} else if (lt->reentrancy <= 0) {
- __ast_mutex_logger("%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
+ log_mutex_error(canlog, "%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
filename, lineno, func, mutex_name);
DO_THREAD_CRASH;
}
#ifdef DEBUG_THREADS
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error waiting on condition mutex '%s'\n",
filename, lineno, func, strerror(res));
DO_THREAD_CRASH;
} else if (lt) {
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
DO_THREAD_CRASH;
return EINVAL;
if (lt) {
ast_reentrancy_lock(lt);
if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
- __ast_mutex_logger("%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
+ log_mutex_error(canlog, "%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
#ifdef HAVE_BKTR
__dump_backtrace(<->backtrace[ROFFSET], canlog);
#endif
DO_THREAD_CRASH;
} else if (lt->reentrancy <= 0) {
- __ast_mutex_logger("%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
+ log_mutex_error(canlog, "%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
filename, lineno, func, mutex_name);
DO_THREAD_CRASH;
}
#ifdef DEBUG_THREADS
if (res && (res != ETIMEDOUT)) {
- __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error waiting on condition mutex '%s'\n",
filename, lineno, func, strerror(res));
DO_THREAD_CRASH;
} else if (lt) {
if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
int canlog = tracking && strcmp(filename, "logger.c");
- __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
filename, lineno, func, rwlock_name);
DO_THREAD_CRASH;
return EBUSY;
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
- __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
filename, lineno, func, rwlock_name);
DO_THREAD_CRASH;
res = EINVAL;
#ifdef DEBUG_THREADS
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error destroying rwlock %s: %s\n",
filename, lineno, func, rwlock_name, strerror(res));
}
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
- __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
filename, line, func, name);
DO_THREAD_CRASH;
return EINVAL;
}
if (lock_found && --lt->reentrancy < 0) {
- __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
+ log_mutex_error(canlog, "%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
filename, line, func, name);
lt->reentrancy = 0;
}
#ifdef DEBUG_THREADS
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error releasing rwlock: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error releasing rwlock: %s\n",
filename, line, func, strerror(res));
DO_THREAD_CRASH;
}
if (res == EBUSY) {
wait_time = time(NULL) - seconds;
if (wait_time > reported_wait && (wait_time % 5) == 0) {
- __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
+ log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
filename, line, func, (int)wait_time, name);
if (lt) {
ast_reentrancy_lock(lt);
#ifdef HAVE_BKTR
__dump_backtrace(<->backtrace[lt->reentrancy], canlog);
#endif
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
lt->func[lt->reentrancy-1], name);
#ifdef HAVE_BKTR
}
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
filename, line, func, strerror(res));
DO_THREAD_CRASH;
}
if (res == EBUSY) {
wait_time = time(NULL) - seconds;
if (wait_time > reported_wait && (wait_time % 5) == 0) {
- __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
+ log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
filename, line, func, (int)wait_time, name);
if (lt) {
ast_reentrancy_lock(lt);
#ifdef HAVE_BKTR
__dump_backtrace(<->backtrace[lt->reentrancy], canlog);
#endif
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
lt->func[lt->reentrancy-1], name);
#ifdef HAVE_BKTR
#endif
}
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error obtaining write lock: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error obtaining write lock: %s\n",
filename, line, func, strerror(res));
DO_THREAD_CRASH;
}
#endif
}
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
filename, line, func, strerror(res));
DO_THREAD_CRASH;
}
#endif
}
if (res) {
- __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
filename, line, func, strerror(res));
DO_THREAD_CRASH;
}
#ifdef DEBUG_THREADS
-#define __ast_mutex_logger(...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
+#define log_mutex_error(canlog, ...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
#ifdef THREAD_CRASH
#define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
if ((t->mutex) != (empty_mutex)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is already initialized.\n",
filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
t->file[0], t->lineno[0], t->func[0], mutex_name);
DO_THREAD_CRASH;
return 0;
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
}
#endif
pthread_mutex_unlock(&t->mutex);
break;
case EINVAL:
- __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
filename, lineno, func, mutex_name);
break;
case EBUSY:
- __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: '%s' was locked here.\n",
t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
break;
}
if ((res = pthread_mutex_destroy(&t->mutex)))
- __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error destroying mutex: %s\n",
filename, lineno, func, strerror(res));
#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
else
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
ast_mutex_init(t);
}
if (res == EBUSY) {
current = time(NULL);
if ((current - seconds) && (!((current - seconds) % 5))) {
- __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
+ log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
filename, lineno, func, (int)(current - seconds), mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
t->func[t->reentrancy-1], mutex_name);
}
t->thread[t->reentrancy] = pthread_self();
t->reentrancy++;
} else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
} else {
- __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error obtaining mutex: %s\n",
filename, lineno, func, strerror(errno));
DO_THREAD_CRASH;
}
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
ast_mutex_init(t);
}
t->thread[t->reentrancy] = pthread_self();
t->reentrancy++;
} else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
} else {
- __ast_mutex_logger("%s line %d (%s): Warning: '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Warning: '%s' was locked here.\n",
t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
}
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
}
#endif
if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
- __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
+ log_mutex_error(canlog, "%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
DO_THREAD_CRASH;
}
if (--t->reentrancy < 0) {
- __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
+ log_mutex_error(canlog, "%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
filename, lineno, func, mutex_name);
t->reentrancy = 0;
}
}
if ((res = pthread_mutex_unlock(&t->mutex))) {
- __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
+ log_mutex_error(canlog, "%s line %d (%s): Error releasing mutex: %s\n",
filename, lineno, func, strerror(res));
DO_THREAD_CRASH;
}