X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-internals.c;h=44f3ff4705fda713c59f27858a989d0ec438491c;hb=3251264ac483680b4a5fe808729f7e3b34f41fd4;hp=e90703e4956917a040789be9375fbe287f0b2d6d;hpb=041b0767b284034aee09e9a0de2a3844b8cc546a;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c index e90703e..44f3ff4 100644 --- a/dbus/dbus-internals.c +++ b/dbus/dbus-internals.c @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-internals.c random utility stuff (internal to D-BUS implementation) * - * Copyright (C) 2002 Red Hat, Inc. + * Copyright (C) 2002, 2003 Red Hat, Inc. * * Licensed under the Academic Free License version 1.2 * @@ -21,6 +21,8 @@ * */ #include "dbus-internals.h" +#include "dbus-protocol.h" +#include "dbus-test.h" #include #include #include @@ -28,6 +30,7 @@ #include #include #include +#include /** * @defgroup DBusInternals D-BUS internal implementation details @@ -104,18 +107,6 @@ * * Maximum value of type "int" */ -/** - * @def _DBUS_MAX_SUN_PATH_LENGTH - * - * Maximum length of the path to a UNIX domain socket, - * sockaddr_un::sun_path member. POSIX requires that all systems - * support at least 100 bytes here, including the nul termination. - * We use 99 for the max value to allow for the nul. - * - * We could probably also do sizeof (addr.sun_path) - * but this way we are the same on all platforms - * which is probably a good idea. - */ /** * @typedef DBusForeachFunction @@ -125,6 +116,48 @@ */ /** + * @def _DBUS_LOCK_NAME + * + * Expands to name of a global lock variable. + */ + +/** + * @def _DBUS_DEFINE_GLOBAL_LOCK + * + * Defines a global lock variable with the given name. + * The lock must be added to the list to initialize + * in dbus_threads_init(). + */ + +/** + * @def _DBUS_DECLARE_GLOBAL_LOCK + * + * Expands to declaration of a global lock defined + * with _DBUS_DEFINE_GLOBAL_LOCK. + * The lock must be added to the list to initialize + * in dbus_threads_init(). + */ + +/** + * @def _DBUS_LOCK + * + * Locks a global lock + */ + +/** + * @def _DBUS_UNLOCK + * + * Unlocks a global lock + */ + +/** + * Fixed "out of memory" error message, just to avoid + * making up a different string every time and wasting + * space. + */ +const char _dbus_no_memory_message[] = "Not enough memory"; + +/** * Prints a warning message to stderr. * * @param format printf-style format string. @@ -141,27 +174,50 @@ _dbus_warn (const char *format, va_end (args); } +static dbus_bool_t verbose_initted = FALSE; + /** * Prints a warning message to stderr * if the user has enabled verbose mode. + * This is the real function implementation, + * use _dbus_verbose() macro in code. * * @param format printf-style format string. */ void -_dbus_verbose (const char *format, - ...) +_dbus_verbose_real (const char *format, + ...) { va_list args; static dbus_bool_t verbose = TRUE; - static dbus_bool_t initted = FALSE; - + static dbus_bool_t need_pid = TRUE; + + /* things are written a bit oddly here so that + * in the non-verbose case we just have the one + * conditional and return immediately. + */ if (!verbose) return; - if (!initted) + if (!verbose_initted) { - verbose = getenv ("DBUS_VERBOSE") != NULL; - initted = TRUE; + verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL; + verbose_initted = TRUE; + if (!verbose) + return; + } + + if (need_pid) + { + int len; + + fprintf (stderr, "%lu: ", _dbus_getpid ()); + + len = strlen (format); + if (format[len-1] == '\n') + need_pid = TRUE; + else + need_pid = FALSE; } va_start (args, format); @@ -170,103 +226,15 @@ _dbus_verbose (const char *format, } /** - * A wrapper around strerror() because some platforms - * may be lame and not have strerror(). + * Reinitializes the verbose logging code, used + * as a hack in dbus-spawn.c so that a child + * process re-reads its pid * - * @param error_number errno. - * @returns error description. */ -const char* -_dbus_strerror (int error_number) -{ - return strerror (error_number); -} - -/** - * Converts a UNIX errno into a DBusResultCode. - * - * @param error_number the errno. - * @returns the result code. - */ -DBusResultCode -_dbus_result_from_errno (int error_number) +void +_dbus_verbose_reset_real (void) { - switch (error_number) - { - case 0: - return DBUS_RESULT_SUCCESS; - -#ifdef EPROTONOSUPPORT - case EPROTONOSUPPORT: - return DBUS_RESULT_NOT_SUPPORTED; -#endif -#ifdef EAFNOSUPPORT - case EAFNOSUPPORT: - return DBUS_RESULT_NOT_SUPPORTED; -#endif -#ifdef ENFILE - case ENFILE: - return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */ -#endif -#ifdef EMFILE - case EMFILE: - return DBUS_RESULT_LIMITS_EXCEEDED; -#endif -#ifdef EACCES - case EACCES: - return DBUS_RESULT_ACCESS_DENIED; -#endif -#ifdef EPERM - case EPERM: - return DBUS_RESULT_ACCESS_DENIED; -#endif -#ifdef ENOBUFS - case ENOBUFS: - return DBUS_RESULT_NO_MEMORY; -#endif -#ifdef ENOMEM - case ENOMEM: - return DBUS_RESULT_NO_MEMORY; -#endif -#ifdef EINVAL - case EINVAL: - return DBUS_RESULT_FAILED; -#endif -#ifdef EBADF - case EBADF: - return DBUS_RESULT_FAILED; -#endif -#ifdef EFAULT - case EFAULT: - return DBUS_RESULT_FAILED; -#endif -#ifdef ENOTSOCK - case ENOTSOCK: - return DBUS_RESULT_FAILED; -#endif -#ifdef EISCONN - case EISCONN: - return DBUS_RESULT_FAILED; -#endif -#ifdef ECONNREFUSED - case ECONNREFUSED: - return DBUS_RESULT_NO_SERVER; -#endif -#ifdef ETIMEDOUT - case ETIMEDOUT: - return DBUS_RESULT_TIMEOUT; -#endif -#ifdef ENETUNREACH - case ENETUNREACH: - return DBUS_RESULT_NO_NETWORK; -#endif -#ifdef EADDRINUSE - case EADDRINUSE: - return DBUS_RESULT_ADDRESS_IN_USE; -#endif - } - - return DBUS_RESULT_FAILED; + verbose_initted = FALSE; } /** @@ -280,7 +248,7 @@ _dbus_result_from_errno (int error_number) char* _dbus_strdup (const char *str) { - int len; + size_t len; char *copy; if (str == NULL) @@ -298,37 +266,298 @@ _dbus_strdup (const char *str) } /** - * Sets a file descriptor to be nonblocking. + * Duplicates a block of memory. Returns + * #NULL on failure. * - * @param fd the file descriptor. - * @param result address of result code. - * @returns #TRUE on success. + * @param mem memory to copy + * @param n_bytes number of bytes to copy + * @returns the copy + */ +void* +_dbus_memdup (const void *mem, + size_t n_bytes) +{ + void *copy; + + copy = dbus_malloc (n_bytes); + if (copy == NULL) + return NULL; + + memcpy (copy, mem, n_bytes); + + return copy; +} + +/** + * Duplicates a string array. Result may be freed with + * dbus_free_string_array(). Returns #NULL if memory allocation fails. + * If the array to be duplicated is #NULL, returns #NULL. + * + * @param array array to duplicate. + * @returns newly-allocated copy. + */ +char** +_dbus_dup_string_array (const char **array) +{ + int len; + int i; + char **copy; + + if (array == NULL) + return NULL; + + for (len = 0; array[len] != NULL; ++len) + ; + + copy = dbus_new0 (char*, len + 1); + if (copy == NULL) + return NULL; + + i = 0; + while (i < len) + { + copy[i] = _dbus_strdup (array[i]); + if (copy[i] == NULL) + { + dbus_free_string_array (copy); + return NULL; + } + + ++i; + } + + return copy; +} + +/** + * Checks whether a string array contains the given string. + * + * @param array array to search. + * @param str string to look for + * @returns #TRUE if array contains string */ dbus_bool_t -_dbus_set_fd_nonblocking (int fd, - DBusResultCode *result) +_dbus_string_array_contains (const char **array, + const char *str) { - int val; + int i; - val = fcntl (fd, F_GETFL, 0); - if (val < 0) + i = 0; + while (array[i] != NULL) { - dbus_set_result (result, _dbus_result_from_errno (errno)); - _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, - _dbus_strerror (errno)); - return FALSE; + if (strcmp (array[i], str) == 0) + return TRUE; + ++i; } - if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) + return FALSE; +} + +/** + * Returns a string describing the given type. + * + * @param type the type to describe + * @returns a constant string describing the type + */ +const char * +_dbus_type_to_string (int type) +{ + switch (type) { - dbus_set_result (result, _dbus_result_from_errno (errno)); - _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", - fd, _dbus_strerror (errno)); + case DBUS_TYPE_INVALID: + return "invalid"; + case DBUS_TYPE_NIL: + return "nil"; + case DBUS_TYPE_BOOLEAN: + return "boolean"; + case DBUS_TYPE_INT32: + return "int32"; + case DBUS_TYPE_UINT32: + return "uint32"; + case DBUS_TYPE_DOUBLE: + return "double"; + case DBUS_TYPE_STRING: + return "string"; + case DBUS_TYPE_NAMED: + return "named"; + case DBUS_TYPE_ARRAY: + return "array"; + case DBUS_TYPE_DICT: + return "dict"; + default: + return "unknown"; + } +} - return FALSE; +/** + * Returns a string describing the given name. + * + * @param header_field the field to describe + * @returns a constant string describing the field + */ +const char * +_dbus_header_field_to_string (int header_field) +{ + switch (header_field) + { + case DBUS_HEADER_FIELD_INVALID: + return "invalid"; + case DBUS_HEADER_FIELD_PATH: + return "path"; + case DBUS_HEADER_FIELD_INTERFACE: + return "interface"; + case DBUS_HEADER_FIELD_MEMBER: + return "member"; + case DBUS_HEADER_FIELD_ERROR_NAME: + return "error-name"; + case DBUS_HEADER_FIELD_REPLY_SERIAL: + return "reply-serial"; + case DBUS_HEADER_FIELD_SERVICE: + return "service"; + case DBUS_HEADER_FIELD_SENDER_SERVICE: + return "sender-service"; + default: + return "unknown"; } +} + +#ifndef DBUS_DISABLE_CHECKS +/** String used in _dbus_return_if_fail macro */ +const char _dbus_return_if_fail_warning_format[] = +"Arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n" +"This is normally a bug in some application using the D-BUS library.\n"; +#endif + +#ifndef DBUS_DISABLE_ASSERT +/** + * Internals of _dbus_assert(); it's a function + * rather than a macro with the inline code so + * that the assertion failure blocks don't show up + * in test suite coverage, and to shrink code size. + * + * @param condition TRUE if assertion succeeded + * @param condition_text condition as a string + * @param file file the assertion is in + * @param line line the assertion is in + */ +void +_dbus_real_assert (dbus_bool_t condition, + const char *condition_text, + const char *file, + int line) +{ + if (!condition) + { + _dbus_warn ("Assertion failed \"%s\" file \"%s\" line %d process %lu\n", + condition_text, file, line, _dbus_getpid ()); + _dbus_abort (); + } +} + +/** + * Internals of _dbus_assert_not_reached(); it's a function + * rather than a macro with the inline code so + * that the assertion failure blocks don't show up + * in test suite coverage, and to shrink code size. + * + * @param explanation what was reached that shouldn't have been + * @param file file the assertion is in + * @param line line the assertion is in + */ +void +_dbus_real_assert_not_reached (const char *explanation, + const char *file, + int line) +{ + _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n", + file, line, _dbus_getpid (), explanation); + _dbus_abort (); +} +#endif /* DBUS_DISABLE_ASSERT */ + +#ifdef DBUS_BUILD_TESTS +static dbus_bool_t +run_failing_each_malloc (int n_mallocs, + const char *description, + DBusTestMemoryFunction func, + void *data) +{ + n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */ + + while (n_mallocs >= 0) + { + _dbus_set_fail_alloc_counter (n_mallocs); + + _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n", + description, n_mallocs, + _dbus_get_fail_alloc_failures ()); + + if (!(* func) (data)) + return FALSE; + + n_mallocs -= 1; + } + + _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); + + return TRUE; +} + +/** + * Tests how well the given function responds to out-of-memory + * situations. Calls the function repeatedly, failing a different + * call to malloc() each time. If the function ever returns #FALSE, + * the test fails. The function should return #TRUE whenever something + * valid (such as returning an error, or succeeding) occurs, and #FALSE + * if it gets confused in some way. + * + * @param description description of the test used in verbose output + * @param func function to call + * @param data data to pass to function + * @returns #TRUE if the function never returns FALSE + */ +dbus_bool_t +_dbus_test_oom_handling (const char *description, + DBusTestMemoryFunction func, + void *data) +{ + int approx_mallocs; + + /* Run once to see about how many mallocs are involved */ + + _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); + + _dbus_verbose ("Running once to count mallocs\n"); + + if (!(* func) (data)) + return FALSE; + + approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter (); + + _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n", + description, approx_mallocs); + + _dbus_set_fail_alloc_failures (1); + if (!run_failing_each_malloc (approx_mallocs, description, func, data)) + return FALSE; + + _dbus_set_fail_alloc_failures (2); + if (!run_failing_each_malloc (approx_mallocs, description, func, data)) + return FALSE; + + _dbus_set_fail_alloc_failures (3); + if (!run_failing_each_malloc (approx_mallocs, description, func, data)) + return FALSE; + + _dbus_set_fail_alloc_failures (4); + if (!run_failing_each_malloc (approx_mallocs, description, func, data)) + return FALSE; + + _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n", + description); return TRUE; } +#endif /* DBUS_BUILD_TESTS */ /** @} */