* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+
+#include <config.h>
#include "dbus-internals.h"
#include "dbus-protocol.h"
#include "dbus-marshal-basic.h"
#include "dbus-test.h"
+#include "dbus-valgrind-internal.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+#include <windows.h>
+#include <mbstring.h>
+#endif
/**
* @defgroup DBusInternals D-Bus secret internal implementation details
*/
/**
- * @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
+ * Locks a global lock, initializing it first if necessary.
+ *
+ * @returns #FALSE if not enough memory
*/
/**
* making up a different string every time and wasting
* space.
*/
-const char _dbus_no_memory_message[] = "Not enough memory";
+const char *_dbus_no_memory_message = "Not enough memory";
static dbus_bool_t warn_initted = FALSE;
static dbus_bool_t fatal_warnings = FALSE;
#include <pthread.h>
#endif
-#ifdef DBUS_WIN
-#define inline
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+static char module_name[1024];
#endif
static inline void
{
if (!verbose_initted)
{
- const char *p = _dbus_getenv ("DBUS_VERBOSE");
+ const char *p = _dbus_getenv ("DBUS_VERBOSE");
verbose = p != NULL && *p == '1';
verbose_initted = TRUE;
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+ {
+ char *last_period, *last_slash;
+ GetModuleFileName(0,module_name,sizeof(module_name)-1);
+ last_period = _mbsrchr(module_name,'.');
+ if (last_period)
+ *last_period ='\0';
+ last_slash = _mbsrchr(module_name,'\\');
+ if (last_slash)
+ strcpy(module_name,last_slash+1);
+ strcat(module_name,": ");
+ }
+#endif
+ }
+}
+
+/** @def DBUS_IS_DIR_SEPARATOR(c)
+ * macro for checking if character c is a patch separator
+ *
+ * @todo move to a header file so that others can use this too
+ */
+#ifdef DBUS_WIN
+#define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/')
+#else
+#define DBUS_IS_DIR_SEPARATOR(c) (c == '/')
+#endif
+
+/**
+ remove source root from file path
+ the source root is determined by
+*/
+static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level)
+{
+ static int prefix = -1;
+
+ if (prefix == -1)
+ {
+ char *p = (char *)file + strlen(file);
+ int i = 0;
+ prefix = 0;
+ for (;p >= file;p--)
+ {
+ if (DBUS_IS_DIR_SEPARATOR(*p))
+ {
+ if (++i >= level)
+ {
+ prefix = p-file+1;
+ break;
+ }
+ }
+ }
}
+ return (char *)file+prefix;
}
/**
* @param format printf-style format string.
*/
void
-_dbus_verbose_real (const char *format,
+_dbus_verbose_real (
+#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+ const char *file,
+ const int line,
+ const char *function,
+#endif
+ const char *format,
...)
{
va_list args;
if (!_dbus_is_verbose_real())
return;
+#ifndef DBUS_USE_OUTPUT_DEBUG_STRING
/* Print out pid before the line */
if (need_pid)
{
fprintf (stderr, "%lu: ", _dbus_pid_for_log ());
#endif
}
-
+#endif
/* Only print pid again if the next line is a new line */
len = strlen (format);
need_pid = TRUE;
else
need_pid = FALSE;
-
+
va_start (args, format);
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+ {
+ char buf[1024];
+ strcpy(buf,module_name);
+#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+ sprintf (buf+strlen(buf), "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
+#endif
+ vsprintf (buf+strlen(buf),format, args);
+ va_end (args);
+ OutputDebugStringA(buf);
+ }
+#else
+#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+ fprintf (stderr, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
+#endif
+
vfprintf (stderr, format, args);
va_end (args);
fflush (stderr);
+#endif
}
/**
verbose_initted = FALSE;
}
+void
+_dbus_trace_ref (const char *obj_name,
+ void *obj,
+ int old_refcount,
+ int new_refcount,
+ const char *why,
+ const char *env_var,
+ int *enabled)
+{
+ _dbus_assert (obj_name != NULL);
+ _dbus_assert (obj != NULL);
+ _dbus_assert (old_refcount >= -1);
+ _dbus_assert (new_refcount >= -1);
+
+ if (old_refcount == -1)
+ {
+ _dbus_assert (new_refcount == -1);
+ }
+ else
+ {
+ _dbus_assert (new_refcount >= 0);
+ _dbus_assert (old_refcount >= 0);
+ _dbus_assert (old_refcount > 0 || new_refcount > 0);
+ }
+
+ _dbus_assert (why != NULL);
+ _dbus_assert (env_var != NULL);
+ _dbus_assert (enabled != NULL);
+
+ if (*enabled < 0)
+ {
+ const char *s = _dbus_getenv (env_var);
+
+ *enabled = FALSE;
+
+ if (s && *s)
+ {
+ if (*s == '0')
+ *enabled = FALSE;
+ else if (*s == '1')
+ *enabled = TRUE;
+ else
+ _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s);
+ }
+ }
+
+ if (*enabled)
+ {
+ if (old_refcount == -1)
+ {
+ VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)",
+ obj_name, obj, why);
+ _dbus_verbose ("%s %p ref stolen (%s)",
+ obj_name, obj, why);
+ }
+ else
+ {
+ VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)",
+ obj_name, obj,
+ old_refcount, new_refcount, why);
+ _dbus_verbose ("%s %p %d -> %d refs (%s)",
+ obj_name, obj, old_refcount, new_refcount, why);
+ }
+ }
+}
+
#endif /* DBUS_ENABLE_VERBOSE_MODE */
/**
{
long now;
- _dbus_get_current_time (&now, NULL);
+ /* don't use monotonic time because the UUID may be saved to disk, e.g.
+ * it may persist across reboots
+ */
+ _dbus_get_real_time (&now, NULL);
uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
goto error;
}
- /* FIXME this is racy; we need a save_file_exclusively
- * function. But in practice this should be fine for now.
- *
- * - first be sure we can create the file and it
- * doesn't exist by creating it empty with O_EXCL
- * - then create it by creating a temporary file and
- * overwriting atomically with rename()
- */
- if (!_dbus_create_file_exclusively (filename, error))
- goto error;
-
if (!_dbus_string_append_byte (&encoded, '\n'))
{
_DBUS_SET_OOM (error);
goto error;
}
- if (!_dbus_string_save_to_file (&encoded, filename, error))
- goto error;
-
- if (!_dbus_make_file_world_readable (filename, error))
+ if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error))
goto error;
_dbus_string_free (&encoded);
}
}
-_DBUS_DEFINE_GLOBAL_LOCK (machine_uuid);
+/* Protected by _DBUS_LOCK (machine_uuid) */
static int machine_uuid_initialized_generation = 0;
static DBusGUID machine_uuid;
{
dbus_bool_t ok;
- _DBUS_LOCK (machine_uuid);
+ if (!_DBUS_LOCK (machine_uuid))
+ return FALSE;
+
if (machine_uuid_initialized_generation != _dbus_current_generation)
{
DBusError error = DBUS_ERROR_INIT;
return ok;
}
-#ifdef DBUS_BUILD_TESTS
-/**
- * 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_DESTINATION:
- return "destination";
- case DBUS_HEADER_FIELD_SENDER:
- return "sender";
- case DBUS_HEADER_FIELD_SIGNATURE:
- return "signature";
- default:
- return "unknown";
- }
-}
-#endif /* DBUS_BUILD_TESTS */
-
#ifndef DBUS_DISABLE_CHECKS
/** String used in _dbus_return_if_fail macro */
-const char _dbus_return_if_fail_warning_format[] =
+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