Пример #1
0
ast_err
Msgtest_read(ast_runtime* rt, Msgtest** msgtest_vp)
{
    ast_err status = AST_NOERR;
    uint32_t wiretype, fieldno;
    Msgtest* msgtest_v;

    msgtest_v = (Msgtest*)ast_alloc(rt,sizeof(Msgtest));
    if(msgtest_v == NULL) return AST_ENOMEM;

    while(status == AST_NOERR) {
        status = ast_read_tag(rt,&wiretype,&fieldno);
        if(status == AST_EOF) {status = AST_NOERR; break;}
        if(status != AST_NOERR) break;
        switch (fieldno) {
        case 1: {
            size_t size;
            if(wiretype != ast_counted) {status=AST_EFAIL; goto done;}
            status = ast_read_size(rt,&size);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
            ast_mark(rt,size);
            status = Submsg_read(rt,&msgtest_v->rmsg);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
            ast_unmark(rt);
            } break;
        case 2: {
            size_t size;
            if(wiretype != ast_counted) {status=AST_EFAIL; goto done;}
            status = ast_read_size(rt,&size);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
            ast_mark(rt,size);
            msgtest_v->omsg.defined = 1;
            msgtest_v->omsg.value = NULL;
            status = Submsg_read(rt,&msgtest_v->omsg.value);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
            ast_unmark(rt);
            } break;
        case 3: {
            size_t size;
            Submsg* tmp;
            if(wiretype != ast_counted) {status=AST_EFAIL; goto done;}
            status = ast_read_size(rt,&size);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
            ast_mark(rt,size);
            status = Submsg_read(rt,&tmp);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
            status = ast_repeat_append(rt,ast_message,&msgtest_v->pmsg,&tmp);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
            ast_unmark(rt);
            } break;
        default:
            status = ast_skip_field(rt,wiretype,fieldno);
            if(status != AST_NOERR) {ACATCH(status); goto done;}
        }; /*switch*/
    };/*while*/
    if(status != AST_NOERR) {ACATCH(status); goto done;}
    if(msgtest_vp) *msgtest_vp = msgtest_v;
done:
    return status;
} /*Msgtest_read*/
Пример #2
0
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
                                           const char* mutex_name, ast_mutex_t *t)
{
	int res;

#ifdef DEBUG_THREADS
	struct ast_lock_track *lt;
	int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef HAVE_BKTR
	struct ast_bt *bt = NULL;
#endif

#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
	if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
		/* Don't warn abount uninitialized mutex.
		 * Simple try to initialize it.
		 * May be not needed in linux system.
		 */
		res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
		if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
			__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
					 filename, lineno, func, mutex_name);
			return res;
		}
	}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */

	if (t->tracking && !t->track) {
		ast_reentrancy_init(&t->track);
	}
	lt = t->track;

	if (t->tracking) {
#ifdef HAVE_BKTR
		ast_reentrancy_lock(lt);
		if (lt->reentrancy != AST_MAX_REENTRANCY) {
			ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
			bt = &lt->backtrace[lt->reentrancy];
		}
		ast_reentrancy_unlock(lt);
		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
#else
		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
#endif
	}
#endif /* DEBUG_THREADS */

#if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
	{
		time_t seconds = time(NULL);
		time_t wait_time, reported_wait = 0;
		do {
#ifdef	HAVE_MTX_PROFILE
			ast_mark(mtx_prof, 1);
#endif
			res = pthread_mutex_trylock(&t->mutex);
#ifdef	HAVE_MTX_PROFILE
			ast_mark(mtx_prof, 0);
#endif
			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",
							   filename, lineno, func, (int) wait_time, mutex_name);
					ast_reentrancy_lock(lt);
#ifdef HAVE_BKTR
					__dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
#endif
					__ast_mutex_logger("%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(&lt->backtrace[ROFFSET], canlog);
#endif
					ast_reentrancy_unlock(lt);
					reported_wait = wait_time;
				}
				usleep(200);
			}
		} while (res == EBUSY);
	}
#else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
#ifdef	HAVE_MTX_PROFILE
	ast_mark(mtx_prof, 1);
	res = pthread_mutex_trylock(&t->mutex);
	ast_mark(mtx_prof, 0);
	if (res)
#endif
	res = pthread_mutex_lock(&t->mutex);
#endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */

#ifdef DEBUG_THREADS
	if (t->tracking && !res) {
		ast_reentrancy_lock(lt);
		if (lt->reentrancy < AST_MAX_REENTRANCY) {
			lt->file[lt->reentrancy] = filename;
			lt->lineno[lt->reentrancy] = lineno;
			lt->func[lt->reentrancy] = func;
			lt->thread[lt->reentrancy] = pthread_self();
			lt->reentrancy++;
		} else {
			__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
							   filename, lineno, func, mutex_name);
		}
		ast_reentrancy_unlock(lt);
		if (t->tracking) {
			ast_mark_lock_acquired(t);
		}
	} else if (t->tracking) {
#ifdef HAVE_BKTR
		if (lt->reentrancy) {
			ast_reentrancy_lock(lt);
			bt = &lt->backtrace[lt->reentrancy-1];
			ast_reentrancy_unlock(lt);
		} else {
			bt = NULL;
		}
		ast_remove_lock_info(t, bt);
#else
		ast_remove_lock_info(t);
#endif
	}
	if (res) {
		__ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
				   filename, lineno, func, strerror(res));
		DO_THREAD_CRASH;
	}
#endif /* DEBUG_THREADS */

	return res;
}
Пример #3
0
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
				const char* mutex_name, ast_mutex_t *t)
{
	int res;

#ifdef DEBUG_THREADS
	struct ast_lock_track *lt = NULL;
	int canlog = t->tracking && strcmp(filename, "logger.c");
#ifdef HAVE_BKTR
	struct ast_bt *bt = NULL;
#endif

	if (t->tracking) {
		lt = ast_get_reentrancy(&t->track);
	}

	if (lt) {
#ifdef HAVE_BKTR
		struct ast_bt tmp;

		/* The implementation of backtrace() may have its own locks.
		 * Capture the backtrace outside of the reentrancy lock to
		 * avoid deadlocks. See ASTERISK-22455. */
		ast_bt_get_addresses(&tmp);

		ast_reentrancy_lock(lt);
		if (lt->reentrancy < AST_MAX_REENTRANCY) {
			lt->backtrace[lt->reentrancy] = tmp;
			bt = &lt->backtrace[lt->reentrancy];
		}
		ast_reentrancy_unlock(lt);

		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
#else
		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
#endif
	}
#endif /* DEBUG_THREADS */

#if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
	{
		time_t seconds = time(NULL);
		time_t wait_time, reported_wait = 0;
		do {
#ifdef	HAVE_MTX_PROFILE
			ast_mark(mtx_prof, 1);
#endif
			res = pthread_mutex_trylock(&t->mutex);
#ifdef	HAVE_MTX_PROFILE
			ast_mark(mtx_prof, 0);
#endif
			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",
							   filename, lineno, func, (int) wait_time, mutex_name);
					if (lt) {
						ast_reentrancy_lock(lt);
#ifdef HAVE_BKTR
						__dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
#endif
						__ast_mutex_logger("%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(&lt->backtrace[ROFFSET], canlog);
#endif
						ast_reentrancy_unlock(lt);
					}
					reported_wait = wait_time;
				}
				usleep(200);
			}
		} while (res == EBUSY);
	}
#else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
#ifdef	HAVE_MTX_PROFILE
	ast_mark(mtx_prof, 1);
	res = pthread_mutex_trylock(&t->mutex);
	ast_mark(mtx_prof, 0);
	if (res)
#endif
	res = pthread_mutex_lock(&t->mutex);
#endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */

#ifdef DEBUG_THREADS
	if (lt && !res) {
		ast_reentrancy_lock(lt);
		if (lt->reentrancy < AST_MAX_REENTRANCY) {
			lt->file[lt->reentrancy] = filename;
			lt->lineno[lt->reentrancy] = lineno;
			lt->func[lt->reentrancy] = func;
			lt->thread[lt->reentrancy] = pthread_self();
			lt->reentrancy++;
		} else {
			__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
							   filename, lineno, func, mutex_name);
		}
		ast_reentrancy_unlock(lt);
		ast_mark_lock_acquired(t);
	} else if (lt) {
#ifdef HAVE_BKTR
		if (lt->reentrancy) {
			ast_reentrancy_lock(lt);
			bt = &lt->backtrace[lt->reentrancy-1];
			ast_reentrancy_unlock(lt);
		} else {
			bt = NULL;
		}
		ast_remove_lock_info(t, bt);
#else
		ast_remove_lock_info(t);
#endif
	}
	if (res) {
		__ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
				   filename, lineno, func, strerror(res));
		DO_THREAD_CRASH;
	}
#endif /* DEBUG_THREADS */

	return res;
}
Пример #4
0
/*
 * This is testing code for astobj
 */
static char *handle_astobj2_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
	struct ao2_container *c1;
	struct ao2_container *c2;
	int i, lim;
	char *obj;
	static int prof_id = -1;
	struct ast_cli_args fake_args = { a->fd, 0, NULL };

	switch (cmd) {
	case CLI_INIT:
		e->command = "astobj2 test";
		e->usage = "Usage: astobj2 test <num>\n"
			   "       Runs astobj2 test. Creates 'num' objects,\n"
			   "       and test iterators, callbacks and maybe other stuff\n";
		return NULL;
	case CLI_GENERATE:
		return NULL;
	}

	if (a->argc != 3) {
		return CLI_SHOWUSAGE;
	}

	if (prof_id == -1) {
		prof_id = ast_add_profile("ao2_alloc", 0);
	}

	ast_cli(a->fd, "argc %d argv %s %s %s\n", a->argc, a->argv[0], a->argv[1], a->argv[2]);
	lim = atoi(a->argv[2]);
	ast_cli(a->fd, "called astobj_test\n");

	handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
	/*
	 * Allocate a list container.
	 */
	c1 = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL /* no sort */,
		NULL /* no callback */, "test");
	ast_cli(a->fd, "container allocated as %p\n", c1);

	/*
	 * fill the container with objects.
	 * ao2_alloc() gives us a reference which we pass to the
	 * container when we do the insert.
	 */
	for (i = 0; i < lim; i++) {
		ast_mark(prof_id, 1 /* start */);
		obj = ao2_t_alloc(80, NULL,"test");
		ast_mark(prof_id, 0 /* stop */);
		ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
		sprintf(obj, "-- this is obj %d --", i);
		ao2_link(c1, obj);
		/* At this point, the refcount on obj is 2 due to the allocation
		 * and linking. We can go ahead and reduce the refcount by 1
		 * right here so that when the container is unreffed later, the
		 * objects will be freed
		 */
		ao2_t_ref(obj, -1, "test");
	}

	ast_cli(a->fd, "testing callbacks\n");
	ao2_t_callback(c1, 0, print_cb, a, "test callback");

	ast_cli(a->fd, "testing container cloning\n");
	c2 = ao2_container_clone(c1, 0);
	if (ao2_container_count(c1) != ao2_container_count(c2)) {
		ast_cli(a->fd, "Cloned container does not have the same number of objects!\n");
	}
	ao2_t_callback(c2, 0, print_cb, a, "test callback");

	ast_cli(a->fd, "testing iterators, remove every second object\n");
	{
		struct ao2_iterator ai;
		int x = 0;

		ai = ao2_iterator_init(c1, 0);
		while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
			ast_cli(a->fd, "iterator on <%s>\n", obj);
			if (x++ & 1)
				ao2_t_unlink(c1, obj,"test");
			ao2_t_ref(obj, -1,"test");
		}
		ao2_iterator_destroy(&ai);
		ast_cli(a->fd, "testing iterators again\n");
		ai = ao2_iterator_init(c1, 0);
		while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
			ast_cli(a->fd, "iterator on <%s>\n", obj);
			ao2_t_ref(obj, -1,"test");
		}
		ao2_iterator_destroy(&ai);
	}

	ast_cli(a->fd, "testing callbacks again\n");
	ao2_t_callback(c1, 0, print_cb, a, "test callback");

	ast_verbose("now you should see an error and possible assertion failure messages:\n");
	ao2_t_ref(&i, -1, "");	/* i is not a valid object so we print an error here */

	ast_cli(a->fd, "destroy container\n");
	ao2_t_ref(c1, -1, "");	/* destroy container */
	ao2_t_ref(c2, -1, "");	/* destroy container */
	handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
	return CLI_SUCCESS;
}