[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