[asterisk-commits] dlee: branch dlee/ASTERISK-22296 r397671 - in /team/dlee/ASTERISK-22296: buil...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Aug 26 16:06:52 CDT 2013
Author: dlee
Date: Mon Aug 26 16:06:51 2013
New Revision: 397671
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=397671
Log:
Comments, clean up
Modified:
team/dlee/ASTERISK-22296/build_tools/cflags.xml
team/dlee/ASTERISK-22296/include/asterisk/ari.h
team/dlee/ASTERISK-22296/include/asterisk/optional_api.h
team/dlee/ASTERISK-22296/main/optional_api.c
team/dlee/ASTERISK-22296/res/ari/ari_websockets.c
Modified: team/dlee/ASTERISK-22296/build_tools/cflags.xml
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/build_tools/cflags.xml?view=diff&rev=397671&r1=397670&r2=397671
==============================================================================
--- team/dlee/ASTERISK-22296/build_tools/cflags.xml (original)
+++ team/dlee/ASTERISK-22296/build_tools/cflags.xml Mon Aug 26 16:06:51 2013
@@ -1,4 +1,4 @@
- <category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes" remove_on_change=".lastclean">
+<category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes" remove_on_change=".lastclean">
<member name="DONT_OPTIMIZE" displayname="Disable Optimizations by the Compiler">
<support_level>core</support_level>
</member>
@@ -27,6 +27,12 @@
<member name="DISABLE_INLINE" displayname="Disable the inline API">
<!-- Added to work around GCC bug
See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47816
+ -->
+ <support_level>extended</support_level>
+ </member>
+ <member name="DISABLE_OPTIONAL_API" displayname="Disable the optional API">
+ <!-- Added to manually disable the optional API, since
+ it's now supported on all systems.
-->
<support_level>extended</support_level>
</member>
Modified: team/dlee/ASTERISK-22296/include/asterisk/ari.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/include/asterisk/ari.h?view=diff&rev=397671&r1=397670&r2=397671
==============================================================================
--- team/dlee/ASTERISK-22296/include/asterisk/ari.h (original)
+++ team/dlee/ASTERISK-22296/include/asterisk/ari.h Mon Aug 26 16:06:51 2013
@@ -33,7 +33,8 @@
#include "asterisk/json.h"
/* Forward-declare websocket structs. This avoids including http_websocket.h,
- * which causes some optional_api monkey business to happen */
+ * which causes optional_api stuff to happen, which makes optional_api more
+ * difficult to debug. */
struct ast_websocket_server;
Modified: team/dlee/ASTERISK-22296/include/asterisk/optional_api.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/include/asterisk/optional_api.h?view=diff&rev=397671&r1=397670&r2=397671
==============================================================================
--- team/dlee/ASTERISK-22296/include/asterisk/optional_api.h (original)
+++ team/dlee/ASTERISK-22296/include/asterisk/optional_api.h Mon Aug 26 16:06:51 2013
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2008, Digium, Inc.
+ * Copyright (C) 2008-2013, Digium, Inc.
*
* Kevin P. Fleming <kpfleming at digium.com>
*
@@ -80,7 +80,7 @@
/*!
* \def AST_OPTIONAL_API(result, name, proto, stub)
- * \brief Define an optional API function
+ * \brief Declare an optional API function
*
* \param result The type of result the function returns
* \param name The name of the function
@@ -96,7 +96,7 @@
/*!
* \def AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)
- * \brief Define an optional API function with compiler attributes
+ * \brief Declare an optional API function with compiler attributes
*
* \param result The type of result the function returns
* \param attr Any compiler attributes to be applied to the function (without the __attribute__ wrapper)
@@ -107,15 +107,73 @@
#if !defined(AST_NO_OPTIONAL_API)
+/*!
+ * \internal
+ * \brief Function pointer to an optional API function.
+ *
+ * Functions that are declared as optional may have any signature they want;
+ * they are cast to this type as needed. We don't use a \c void pointer, because
+ * technically data and function pointers are incompatible.
+ */
typedef void (*ast_optional_fn)(void);
+/*!
+ * \internal
+ * \brief Provide an implementation of an optional API.
+ *
+ * Any declared usages of this function are linked.
+ *
+ * \param symname Name of the provided function.
+ * \param impl Function pointer to the implementation function.
+ */
void ast_optional_api_provide(const char *symname, ast_optional_fn impl);
+
+/*!
+ * \internal
+ * \brief Remove an implementation of an optional API.
+ *
+ * Any declared usages of this function are unlinked.
+ *
+ * \param symname Name of the provided function.
+ * \param impl Function pointer to the implementation function.
+ */
void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl);
+
+/*!
+ * \internal
+ * \brief Define a usage of an optional API.
+ *
+ * If the API has been provided, it will be linked into \a optional_ref.
+ * Otherwise, it will be linked to \a stub until an implementation is provided.
+ *
+ * \param symname Name of the function to use.
+ * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
+ * \param stub Stub function to link to when impl is not available.
+ * \param module Name of the module requesting the API.
+ */
void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,
ast_optional_fn stub, const char *module);
-void ast_optional_api_unuse(const char *symname, ast_optional_fn *function,
+
+/*!
+ * \internal
+ * \brief Remove a usage of an optional API.
+ *
+ * The \a optional_ref will be linked to the \a stub provided at use time,
+ * will no longer be updated if the API is provided/removed.
+ *
+ * \param symname Name of the function to use.
+ * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
+ * \param module Name of the module requesting the API.
+ */
+void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref,
const char *module);
+/*!
+ * \brief Call at exit to clean up optional_api internals.
+ *
+ * Since the optional_api code might run before main() starts, it can't safely
+ * register its own cleanup handlers. That has to be done withing main().
+ */
void optional_api_cleanup(void);
#define AST_OPTIONAL_API_NAME(name) __##name
Modified: team/dlee/ASTERISK-22296/main/optional_api.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/main/optional_api.c?view=diff&rev=397671&r1=397670&r2=397671
==============================================================================
--- team/dlee/ASTERISK-22296/main/optional_api.c (original)
+++ team/dlee/ASTERISK-22296/main/optional_api.c Mon Aug 26 16:06:51 2013
@@ -28,37 +28,66 @@
*
* The calls to ast_optional_api_*() happen implicitly from \c __constructor__
* calls which are defined in header files. This means that some number of them
- * happen before main() is called. This makes calling into any other Asterisk
- * API a dangerous thing, because we don't know if they've been initialized yet.
- */
-
+ * happen before main() is called. This makes calling most Asterisk APIs
+ * dangerous, since we could be called before they are initialized. This
+ * includes things like AO2, malloc debug, and static mutexes.
+ *
+ * Fortunately, there are some constraints that help us out. The \c
+ * ast_optional_api_*() are called during module loads, which happens either
+ * before main(), or during dlopen() calls. These are already serialized, so we
+ * don't have to lock ourselves.
+ *
+ * Another limitation in this implementation is that most functions are called
+ * from the midst of dlopen() or dlclose(), and there is no opportunity to
+ * return a failure code. The best we can do is log an error, and call
+ * ast_do_crash().
+ */
+
+/*! \brief A user of an optional API */
struct optional_api_user {
+ /*! Pointer to function pointer to link */
ast_optional_fn *optional_ref;
+ /*! Stub to use when impl is unavailable */
ast_optional_fn stub;
+ /*! Name of the module using the API */
char module[];
};
+/*! \brief An optional API */
struct optional_api {
+ /*! Pointer to the implementation function; could be null */
ast_optional_fn impl;
+ /*! Variable length array of users of this API */
struct optional_api_user **users;
+ /*! Allocated size of the \a users array */
size_t users_maxlen;
+ /*! Number of entries in the \a users array */
size_t users_len;
+ /*! Name of the optional API function */
char symname[];
};
-static void optional_api_free(struct optional_api *api)
-{
- free(api->users);
- api->users = NULL;
- free(api);
-}
-
-static void optional_api_user_free(struct optional_api_user *user)
-{
- ast_assert(*user->optional_ref == user->stub);
+/*!
+ * \brief Free an \ref optional_api_user.
+ *
+ * \param user User struct to free.
+ */
+static void optional_api_user_destroy(struct optional_api_user *user)
+{
+ *user->optional_ref = user->stub;
free(user);
}
+/*!
+ * \brief Create an \ref optional_api_user.
+ *
+ * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
+ * \param stub Stub function to link to when impl is not available.
+ * \param module Name of the module requesting the API.
+ *
+ * \return New \ref optional_api_user.
+ * \return \c NULL on error.
+ */
static struct optional_api_user *optional_api_user_create(
ast_optional_fn *optional_ref, ast_optional_fn stub, const char *module)
{
@@ -78,32 +107,78 @@
return user;
}
+/*!
+ * \brief Free an \ref optional_api.
+ *
+ * \param api API struct to free.
+ */
+static void optional_api_destroy(struct optional_api *api)
+{
+ while (api->users_len--) {
+ optional_api_user_destroy(api->users[api->users_len]);
+ }
+ free(api->users);
+ api->users = NULL;
+ api->users_maxlen = 0;
+ free(api);
+}
+
+/*!
+ * \brief Create an \ref optional_api.
+ *
+ * \param symname Name of the optional function.
+ * \return New \ref optional_api.
+ * \return \c NULL on error.
+ */
+static struct optional_api *optional_api_create(const char *symname)
+{
+ struct optional_api *api;
+ size_t size;
+
+ ast_verb(6, "%s: building api object\n", symname);
+ size = sizeof(*api) + strlen(symname) + 1;
+ api = calloc(1, size);
+ if (!api) {
+ ast_log(LOG_ERROR, "Failed to allocate api\n");
+ return NULL;
+ }
+
+ /* safe strcpy */
+ strcpy(api->symname, symname);
+
+ return api;
+}
+
+/*! Array of \ref optional_api functions */
struct {
+ /*! Variable length array of API's */
struct optional_api **list;
+ /*! Allocated size of the \a list array */
size_t maxlen;
+ /*! Number of entries in the \a list array */
size_t len;
} apis;
-/* optional_api may run before main(), so it can't register its own cleanup.
- * This gets registered in main().
- */
void optional_api_cleanup(void)
{
- size_t i;
-
- for (i = 0; i < apis.len; ++i) {
- optional_api_free(apis.list[i]);
- }
- apis.len = 0;
+ while (apis.len--) {
+ optional_api_destroy(apis.list[apis.len]);
+ }
free(apis.list);
apis.list = NULL;
apis.maxlen = 0;
}
+/*!
+ * \brief Gets (or creates) the \ref optional_api for the give function.
+ *
+ * \param sysname Name of the function to look up.
+ * \return Corresponding \ref optional_api.
+ * \return \c NULL on error.
+ */
static struct optional_api *get_api(const char *symname)
{
struct optional_api *api;
- size_t size;
size_t i;
/* Find one, if we already have it */
@@ -114,16 +189,7 @@
}
/* API not found. Build one */
- ast_verb(6, "%s: building api object\n", symname);
- size = sizeof(*api) + strlen(symname) + 1;
- api = calloc(1, size);
- if (!api) {
- ast_log(LOG_ERROR, "Failed to allocate api\n");
- return NULL;
- }
-
- /* safe strcpy */
- strcpy(api->symname, symname);
+ api = optional_api_create(symname);
/* Grow the list, if needed */
if (apis.len + 1 > apis.maxlen) {
@@ -132,7 +198,7 @@
realloc(apis.list, new_maxlen * sizeof(*new_list));
if (!new_list) {
- ast_free(api);
+ optional_api_destroy(api);
ast_log(LOG_ERROR, "Failed to allocate api list\n");
return NULL;
}
@@ -146,6 +212,15 @@
return api;
}
+/*!
+ * \brief Re-links a given \a user against its associated \a api.
+ *
+ * If the \a api has an implementation, the \a user is linked to that
+ * implementation. Otherwise, the \a user is linked to its \a stub.
+ *
+ * \param user \ref optional_api_user to link.
+ * \param api \ref optional_api to link.
+ */
static void optional_api_user_relink(struct optional_api_user *user,
struct optional_api *api)
{
@@ -159,6 +234,13 @@
}
}
+/*!
+ * \brief Sets the implementation function pointer for an \a api.
+ *
+ * \param api API to implement/stub out.
+ * \param impl Pointer to implementation function. Can be 0 to remove
+ * implementation.
+ */
static void optional_api_set_impl(struct optional_api *api,
ast_optional_fn impl)
{
@@ -181,6 +263,7 @@
api = get_api(symname);
if (!api) {
ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);
+ ast_do_crash();
return;
}
@@ -196,6 +279,7 @@
api = get_api(symname);
if (!api) {
ast_log(LOG_ERROR, "%s: Could not find api\n", symname);
+ ast_do_crash();
return;
}
@@ -212,12 +296,14 @@
api = get_api(symname);
if (!api) {
ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);
+ ast_do_crash();
return;
}
user = optional_api_user_create(optional_ref, stub, module);
if (!user) {
ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);
+ ast_do_crash();
return;
}
@@ -229,11 +315,9 @@
realloc(api->users, new_maxlen * sizeof(*new_list));
if (!new_list) {
- ast_free(user);
+ optional_api_user_destroy(user);
ast_log(LOG_ERROR, "Failed to allocate api list\n");
- /* Called during module load; no way to return failure.
- * assert false and hope for the best */
- ast_assert(0);
+ ast_do_crash();
return;
}
@@ -255,6 +339,7 @@
api = get_api(symname);
if (!api) {
ast_log(LOG_ERROR, "%s: Could not find api\n", symname);
+ ast_do_crash();
return;
}
@@ -263,15 +348,17 @@
if (user->optional_ref == optional_ref) {
if (*user->optional_ref != user->stub) {
ast_verb(4, "%s: stubbing for %s\n", symname,
- user->module);
+ module);
*user->optional_ref = user->stub;
}
/* Remove from the list */
api->users[i] = api->users[--api->users_len];
- optional_api_user_free(user);
- break;
+ optional_api_user_destroy(user);
+ return;
}
}
-}
+
+ ast_log(LOG_ERROR, "%s: Could not find user %s\n", symname, module);
+}
Modified: team/dlee/ASTERISK-22296/res/ari/ari_websockets.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/ari/ari_websockets.c?view=diff&rev=397671&r1=397670&r2=397671
==============================================================================
--- team/dlee/ASTERISK-22296/res/ari/ari_websockets.c (original)
+++ team/dlee/ASTERISK-22296/res/ari/ari_websockets.c Mon Aug 26 16:06:51 2013
@@ -23,6 +23,7 @@
#include "asterisk/ari.h"
#include "asterisk/astobj2.h"
#include "asterisk/http_websocket.h"
+#include "internal.h"
/*! \file
*
More information about the asterisk-commits
mailing list