dbus/test/glib/test-profile.c

1151 lines
30 KiB
C
Raw Normal View History

2003-09-30 02:43:21 +00:00
/* -*- mode: C; c-file-style: "gnu" -*- */
/* test-profile.c Program that does basic message-response for timing; doesn't really use glib bindings
2003-09-30 02:43:21 +00:00
*
* Copyright (C) 2003, 2004 Red Hat Inc.
2003-09-30 02:43:21 +00:00
*
* Licensed under the Academic Free License version 2.1
2003-09-30 02:43:21 +00:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include <glib.h>
#include <dbus/dbus-glib-lowlevel.h>
2003-09-30 02:43:21 +00:00
#include <stdlib.h>
#include <unistd.h>
2003-09-30 02:43:21 +00:00
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/time.h>
#include <sys/stat.h>
#ifndef HAVE_SOCKLEN_T
#define socklen_t int
#endif
#define _DBUS_ZERO(object) (memset (&(object), '\0', sizeof ((object))))
#define _DBUS_MAX_SUN_PATH_LENGTH 99
/* Note that if you set threads > 1 you get a bogus profile since the
* clients start blocking on the server, so the client write() will go
* higher in the profile the larger the number of threads.
*/
#define N_CLIENT_THREADS 1
/* It seems like at least 750000 or so iterations reduces the variability to sane levels */
#define N_ITERATIONS 750000
#define N_PROGRESS_UPDATES 20
/* Don't make PAYLOAD_SIZE too huge because it gets used as a static buffer size */
#define PAYLOAD_SIZE 0
#define ECHO_SERVICE "org.freedesktop.EchoTestServer"
2003-09-30 02:43:21 +00:00
#define ECHO_PATH "/org/freedesktop/EchoTest"
#define ECHO_INTERFACE "org.freedesktop.EchoTest"
#define ECHO_PING_METHOD "Ping"
2003-09-30 02:43:21 +00:00
static const char *messages_address;
static const char *plain_sockets_address;
2003-09-30 02:43:21 +00:00
static unsigned char *payload;
static int echo_call_size;
static int echo_return_size;
2003-09-30 02:43:21 +00:00
typedef struct ProfileRunVTable ProfileRunVTable;
typedef struct
{
const ProfileRunVTable *vtable;
int iterations;
GMainLoop *loop;
} ClientData;
typedef struct
{
const ProfileRunVTable *vtable;
int handled;
GMainLoop *loop;
int n_clients;
} ServerData;
struct ProfileRunVTable
{
const char *name;
gboolean fake_malloc_overhead;
void* (* init_server) (ServerData *sd);
void (* stop_server) (ServerData *sd,
void *server);
void* (* client_thread_func) (void *data); /* Data has to be the vtable */
/* this is so different runs show up in the profiler with
* different backtrace
*/
void (* main_loop_run_func) (GMainLoop *loop);
};
/* Note, this is all crack-a-rific; it isn't using DBusGProxy and thus is
* a major pain
*/
2003-09-30 02:43:21 +00:00
static void
send_echo_method_call (DBusConnection *connection)
2003-09-30 02:43:21 +00:00
{
DBusMessage *message;
2005-01-15 Havoc Pennington <hp@redhat.com> * Land the new message args API and type system. This patch is huge, but the public API change is not really large. The set of D-BUS types has changed somewhat, and the arg "getters" are more geared toward language bindings; they don't make a copy, etc. There are also some known issues. See these emails for details on this huge patch: http://lists.freedesktop.org/archives/dbus/2004-December/001836.html http://lists.freedesktop.org/archives/dbus/2005-January/001922.html * dbus/dbus-marshal-*: all the new stuff * dbus/dbus-message.c: basically rewritten * dbus/dbus-memory.c (check_guards): with "guards" enabled, init freed blocks to be all non-nul bytes so using freed memory is less likely to work right * dbus/dbus-internals.c (_dbus_test_oom_handling): add DBUS_FAIL_MALLOC=N environment variable, so you can do DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or DBUS_FAIL_MALLOC=10 to make it really, really, really slow and thorough. * qt/message.cpp: port to the new message args API (operator<<): use str.utf8() rather than str.unicode() (pretty sure this is right from the Qt docs?) * glib/dbus-gvalue.c: port to the new message args API * bus/dispatch.c, bus/driver.c: port to the new message args API * dbus/dbus-string.c (_dbus_string_init_const_len): initialize the "locked" flag to TRUE and align_offset to 0; I guess we never looked at these anyhow, but seems cleaner. * dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING): move allocation padding macro to this header; use it to implement (_DBUS_STRING_STATIC): ability to declare a static string. * dbus/dbus-message.c (_dbus_message_has_type_interface_member): change to return TRUE if the interface is not set. * dbus/dbus-string.[hc]: move the D-BUS specific validation stuff to dbus-marshal-validate.[hc] * dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from dbus-internals.c * dbus/Makefile.am: cut over from dbus-marshal.[hc] to dbus-marshal-*.[hc] * dbus/dbus-object-tree.c (_dbus_decompose_path): move this function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
const char *hello = "Hello World!";
dbus_int32_t i32 = 123456;
2003-09-30 02:43:21 +00:00
message = dbus_message_new_method_call (ECHO_SERVICE,
ECHO_PATH,
ECHO_INTERFACE,
ECHO_PING_METHOD);
2003-09-30 02:43:21 +00:00
dbus_message_append_args (message,
2005-01-15 Havoc Pennington <hp@redhat.com> * Land the new message args API and type system. This patch is huge, but the public API change is not really large. The set of D-BUS types has changed somewhat, and the arg "getters" are more geared toward language bindings; they don't make a copy, etc. There are also some known issues. See these emails for details on this huge patch: http://lists.freedesktop.org/archives/dbus/2004-December/001836.html http://lists.freedesktop.org/archives/dbus/2005-January/001922.html * dbus/dbus-marshal-*: all the new stuff * dbus/dbus-message.c: basically rewritten * dbus/dbus-memory.c (check_guards): with "guards" enabled, init freed blocks to be all non-nul bytes so using freed memory is less likely to work right * dbus/dbus-internals.c (_dbus_test_oom_handling): add DBUS_FAIL_MALLOC=N environment variable, so you can do DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or DBUS_FAIL_MALLOC=10 to make it really, really, really slow and thorough. * qt/message.cpp: port to the new message args API (operator<<): use str.utf8() rather than str.unicode() (pretty sure this is right from the Qt docs?) * glib/dbus-gvalue.c: port to the new message args API * bus/dispatch.c, bus/driver.c: port to the new message args API * dbus/dbus-string.c (_dbus_string_init_const_len): initialize the "locked" flag to TRUE and align_offset to 0; I guess we never looked at these anyhow, but seems cleaner. * dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING): move allocation padding macro to this header; use it to implement (_DBUS_STRING_STATIC): ability to declare a static string. * dbus/dbus-message.c (_dbus_message_has_type_interface_member): change to return TRUE if the interface is not set. * dbus/dbus-string.[hc]: move the D-BUS specific validation stuff to dbus-marshal-validate.[hc] * dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from dbus-internals.c * dbus/Makefile.am: cut over from dbus-marshal.[hc] to dbus-marshal-*.[hc] * dbus/dbus-object-tree.c (_dbus_decompose_path): move this function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
DBUS_TYPE_STRING, &hello,
DBUS_TYPE_INT32, &i32,
#if PAYLOAD_SIZE > 0
2003-09-30 02:43:21 +00:00
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
2005-01-15 Havoc Pennington <hp@redhat.com> * Land the new message args API and type system. This patch is huge, but the public API change is not really large. The set of D-BUS types has changed somewhat, and the arg "getters" are more geared toward language bindings; they don't make a copy, etc. There are also some known issues. See these emails for details on this huge patch: http://lists.freedesktop.org/archives/dbus/2004-December/001836.html http://lists.freedesktop.org/archives/dbus/2005-January/001922.html * dbus/dbus-marshal-*: all the new stuff * dbus/dbus-message.c: basically rewritten * dbus/dbus-memory.c (check_guards): with "guards" enabled, init freed blocks to be all non-nul bytes so using freed memory is less likely to work right * dbus/dbus-internals.c (_dbus_test_oom_handling): add DBUS_FAIL_MALLOC=N environment variable, so you can do DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or DBUS_FAIL_MALLOC=10 to make it really, really, really slow and thorough. * qt/message.cpp: port to the new message args API (operator<<): use str.utf8() rather than str.unicode() (pretty sure this is right from the Qt docs?) * glib/dbus-gvalue.c: port to the new message args API * bus/dispatch.c, bus/driver.c: port to the new message args API * dbus/dbus-string.c (_dbus_string_init_const_len): initialize the "locked" flag to TRUE and align_offset to 0; I guess we never looked at these anyhow, but seems cleaner. * dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING): move allocation padding macro to this header; use it to implement (_DBUS_STRING_STATIC): ability to declare a static string. * dbus/dbus-message.c (_dbus_message_has_type_interface_member): change to return TRUE if the interface is not set. * dbus/dbus-string.[hc]: move the D-BUS specific validation stuff to dbus-marshal-validate.[hc] * dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from dbus-internals.c * dbus/Makefile.am: cut over from dbus-marshal.[hc] to dbus-marshal-*.[hc] * dbus/dbus-object-tree.c (_dbus_decompose_path): move this function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
&payload, PAYLOAD_SIZE,
2003-09-30 02:43:21 +00:00
#endif
DBUS_TYPE_INVALID);
dbus_connection_send (connection, message, NULL);
dbus_message_unref (message);
dbus_connection_flush (connection);
}
static void
send_echo_method_return (DBusConnection *connection,
DBusMessage *call_message)
{
DBusMessage *message;
message = dbus_message_new_method_return (call_message);
dbus_connection_send (connection, message, NULL);
dbus_message_unref (message);
dbus_connection_flush (connection);
}
2003-09-30 02:43:21 +00:00
static DBusHandlerResult
with_or_without_bus_client_filter (DBusConnection *connection,
DBusMessage *message,
ClientData *cd)
2003-09-30 02:43:21 +00:00
{
if (dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
"Disconnected"))
{
g_printerr ("Client thread disconnected\n");
exit (1);
}
else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
2003-09-30 02:43:21 +00:00
{
cd->iterations += 1;
if (cd->iterations >= N_ITERATIONS)
2003-09-30 02:43:21 +00:00
{
g_printerr ("\nCompleted %d iterations\n", N_ITERATIONS);
g_main_loop_quit (cd->loop);
2003-09-30 02:43:21 +00:00
}
else if (cd->iterations % (N_ITERATIONS/N_PROGRESS_UPDATES) == 0)
{
g_printerr ("%d%% ", (int) (cd->iterations/(double)N_ITERATIONS * 100.0));
}
send_echo_method_call (connection);
2003-09-30 02:43:21 +00:00
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static DBusHandlerResult
no_bus_client_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
ClientData *cd = user_data;
return with_or_without_bus_client_filter (connection, message, cd);
}
2003-09-30 02:43:21 +00:00
static void*
no_bus_thread_func (void *data)
2003-09-30 02:43:21 +00:00
{
DBusError error;
GMainContext *context;
DBusConnection *connection;
ClientData cd;
2003-09-30 02:43:21 +00:00
g_printerr ("Starting client thread %p\n", g_thread_self());
2003-09-30 02:43:21 +00:00
dbus_error_init (&error);
connection = dbus_connection_open (messages_address, &error);
2003-09-30 02:43:21 +00:00
if (connection == NULL)
{
g_printerr ("could not open connection: %s\n", error.message);
dbus_error_free (&error);
exit (1);
}
context = g_main_context_new ();
cd.iterations = 1;
cd.loop = g_main_loop_new (context, FALSE);
2003-09-30 02:43:21 +00:00
if (!dbus_connection_add_filter (connection,
no_bus_client_filter, &cd, NULL))
2003-09-30 02:43:21 +00:00
g_error ("no memory");
dbus_connection_setup_with_g_main (connection, context);
g_printerr ("Client thread sending message to prime pingpong\n");
send_echo_method_call (connection);
2003-09-30 02:43:21 +00:00
g_printerr ("Client thread sent message\n");
g_printerr ("Client thread entering main loop\n");
g_main_loop_run (cd.loop);
g_printerr ("Client thread %p exiting main loop\n",
g_thread_self());
dbus_connection_disconnect (connection);
2003-09-30 02:43:21 +00:00
g_main_loop_unref (cd.loop);
2003-09-30 02:43:21 +00:00
g_main_context_unref (context);
2003-09-30 02:43:21 +00:00
return NULL;
}
static DBusHandlerResult
no_bus_server_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
2003-09-30 02:43:21 +00:00
{
ServerData *sd = user_data;
2003-09-30 02:43:21 +00:00
if (dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
"Disconnected"))
{
g_printerr ("Client disconnected from server\n");
sd->n_clients -= 1;
if (sd->n_clients == 0)
g_main_loop_quit (sd->loop);
2003-09-30 02:43:21 +00:00
}
else if (dbus_message_is_method_call (message,
ECHO_INTERFACE,
ECHO_PING_METHOD))
2003-09-30 02:43:21 +00:00
{
sd->handled += 1;
send_echo_method_return (connection, message);
2003-09-30 02:43:21 +00:00
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static void
no_bus_new_connection_callback (DBusServer *server,
DBusConnection *new_connection,
void *user_data)
{
ServerData *sd = user_data;
2003-09-30 02:43:21 +00:00
dbus_connection_ref (new_connection);
dbus_connection_setup_with_g_main (new_connection, NULL);
if (!dbus_connection_add_filter (new_connection,
no_bus_server_filter, sd, NULL))
2003-09-30 02:43:21 +00:00
g_error ("no memory");
sd->n_clients += 1;
2003-09-30 02:43:21 +00:00
/* FIXME we leak the handler */
}
static void*
no_bus_init_server (ServerData *sd)
2003-09-30 02:43:21 +00:00
{
DBusServer *server;
DBusError error;
2003-09-30 02:43:21 +00:00
dbus_error_init (&error);
server = dbus_server_listen ("unix:tmpdir="DBUS_TEST_SOCKET_DIR,
&error);
if (server == NULL)
{
g_printerr ("Could not start server: %s\n",
error.message);
exit (1);
2003-09-30 02:43:21 +00:00
}
messages_address = dbus_server_get_address (server);
2003-09-30 02:43:21 +00:00
dbus_server_set_new_connection_function (server,
no_bus_new_connection_callback,
sd, NULL);
dbus_server_setup_with_g_main (server, NULL);
return server;
}
static void
no_bus_stop_server (ServerData *sd,
void *server)
{
g_printerr ("The following g_warning is because we try to call g_source_remove_poll() after g_source_destroy() in dbus-gmain.c, I think we need to add a source free func that clears out the watch/timeout funcs\n");
dbus_server_unref (server);
}
static void
no_bus_main_loop_run (GMainLoop *loop)
{
g_main_loop_run (loop);
}
static const ProfileRunVTable no_bus_vtable = {
"dbus direct without bus",
FALSE,
no_bus_init_server,
no_bus_stop_server,
no_bus_thread_func,
no_bus_main_loop_run
};
typedef struct
{
const ProfileRunVTable *vtable;
ServerData *sd;
GHashTable *client_names;
DBusConnection *connection;
} WithBusServer;
static DBusHandlerResult
with_bus_client_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
ClientData *cd = user_data;
return with_or_without_bus_client_filter (connection, message, cd);
}
static void*
with_bus_thread_func (void *data)
{
DBusError error;
DBusConnection *connection;
ClientData cd;
const char *address;
GMainContext *context;
g_printerr ("Starting client thread %p\n", g_thread_self());
address = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
if (address == NULL)
{
g_printerr ("DBUS_SESSION_BUS_ADDRESS not set\n");
exit (1);
}
dbus_error_init (&error);
connection = dbus_connection_open (address, &error);
if (connection == NULL)
{
g_printerr ("could not open connection to bus: %s\n", error.message);
dbus_error_free (&error);
exit (1);
}
if (!dbus_bus_register (connection, &error))
{
g_printerr ("could not register with bus: %s\n", error.message);
dbus_error_free (&error);
exit (1);
}
context = g_main_context_new ();
cd.iterations = 1;
cd.loop = g_main_loop_new (context, FALSE);
if (!dbus_connection_add_filter (connection,
with_bus_client_filter, &cd, NULL))
g_error ("no memory");
dbus_connection_setup_with_g_main (connection, context);
g_printerr ("Client thread sending message to prime pingpong\n");
send_echo_method_call (connection);
g_printerr ("Client thread sent message\n");
g_printerr ("Client thread entering main loop\n");
g_main_loop_run (cd.loop);
g_printerr ("Client thread %p exiting main loop\n",
g_thread_self());
dbus_connection_disconnect (connection);
g_main_loop_unref (cd.loop);
g_main_context_unref (context);
return NULL;
}
static DBusHandlerResult
with_bus_server_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
WithBusServer *server = user_data;
if (dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
"Disconnected"))
{
g_printerr ("Server disconnected from message bus\n");
exit (1);
}
else if (dbus_message_has_sender (message,
DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) &&
dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
"ServiceOwnerChanged"))
{
const char *service_name, *old_owner, *new_owner;
DBusError error;
service_name = NULL;
old_owner = NULL;
new_owner = NULL;
dbus_error_init (&error);
if (!dbus_message_get_args (message,
&error,
DBUS_TYPE_STRING, &service_name,
DBUS_TYPE_STRING, &old_owner,
DBUS_TYPE_STRING, &new_owner,
DBUS_TYPE_INVALID))
{
g_printerr ("dbus_message_get_args(): %s\n", error.message);
exit (1);
}
if (g_hash_table_lookup (server->client_names,
service_name) &&
*old_owner != '\0' &&
*new_owner == '\0')
{
g_hash_table_remove (server->client_names,
service_name);
server->sd->n_clients -= 1;
if (server->sd->n_clients == 0)
g_main_loop_quit (server->sd->loop);
}
}
else if (dbus_message_is_method_call (message,
ECHO_INTERFACE,
ECHO_PING_METHOD))
{
const char *sender;
sender = dbus_message_get_sender (message);
if (!g_hash_table_lookup (server->client_names,
sender))
{
g_printerr ("First message from new client %s on bus\n", sender);
g_hash_table_replace (server->client_names,
g_strdup (sender),
GINT_TO_POINTER (1));
server->sd->n_clients += 1;
}
server->sd->handled += 1;
send_echo_method_return (connection, message);
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static void*
with_bus_init_server (ServerData *sd)
{
DBusGConnection *gconnection;
DBusConnection *connection;
GError *gerror;
const char *s;
WithBusServer *server;
char *rule;
server = g_new0 (WithBusServer, 1);
server->vtable = sd->vtable;
server->sd = sd;
s = g_getenv ("DBUS_TEST_GLIB_RUN_TEST_SCRIPT");
if (s == NULL ||
*s != '1')
{
g_printerr ("You have to run with_bus mode with the run-test.sh script\n");
exit (1);
}
/* Note that we use the standard global bus connection for the
* server, and the clients open their own connections so they can
* have their own main loops and because I'm not sure "talking to
* yourself" really works yet
*/
gerror = NULL;
gconnection = dbus_g_bus_get (DBUS_BUS_SESSION, &gerror);
if (gconnection == NULL)
{
g_printerr ("could not open connection to bus: %s\n", gerror->message);
g_error_free (gerror);
exit (1);
}
server->client_names = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
connection = dbus_g_connection_get_connection (gconnection);
dbus_bus_acquire_service (connection,
ECHO_SERVICE,
0, NULL); /* ignore errors because we suck */
rule = g_strdup_printf ("type='signal',sender='%s',member='%s'",
DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
"ServiceOwnerChanged");
/* ignore errors because we suck */
dbus_bus_add_match (connection, rule, NULL);
g_free (rule);
if (!dbus_connection_add_filter (connection,
with_bus_server_filter, server, NULL))
g_error ("no memory");
server->connection = connection;
server->client_names = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
return server;
}
static void
with_bus_stop_server (ServerData *sd,
void *serverv)
{
WithBusServer *server = serverv;
dbus_connection_remove_filter (server->connection,
with_bus_server_filter, server);
g_hash_table_destroy (server->client_names);
dbus_connection_unref (server->connection);
g_free (server);
}
static void
with_bus_main_loop_run (GMainLoop *loop)
{
g_main_loop_run (loop);
}
static const ProfileRunVTable with_bus_vtable = {
"routing via a bus",
FALSE,
with_bus_init_server,
with_bus_stop_server,
with_bus_thread_func,
with_bus_main_loop_run
};
typedef struct
{
const ProfileRunVTable *vtable;
int listen_fd;
ServerData *sd;
unsigned int source_id;
} PlainSocketServer;
static void
read_and_drop_on_floor (int fd,
int count,
gboolean fake_malloc_overhead)
{
int bytes_read;
int val;
char *buf;
char *allocated;
char not_allocated[512+PAYLOAD_SIZE];
g_assert (count < (int) sizeof(not_allocated));
if (fake_malloc_overhead)
{
allocated = g_malloc (count);
buf = allocated;
}
else
{
allocated = NULL;
buf = not_allocated;
}
bytes_read = 0;
while (bytes_read < count)
{
again:
val = read (fd, buf + bytes_read, count - bytes_read);
if (val < 0)
{
if (errno == EINTR)
goto again;
else
{
g_printerr ("read() failed thread %p: %s\n",
g_thread_self(), strerror (errno));
exit (1);
}
}
else
{
bytes_read += val;
}
}
if (fake_malloc_overhead)
g_free (allocated);
#if 0
g_printerr ("%p read %d bytes from fd %d\n",
g_thread_self(), bytes_read, fd);
#endif
}
static void
write_junk (int fd,
int count,
gboolean fake_malloc_overhead)
{
int bytes_written;
int val;
char *buf;
char *allocated;
char not_allocated[512+PAYLOAD_SIZE];
g_assert (count < (int) sizeof(not_allocated));
if (fake_malloc_overhead)
{
int i;
allocated = g_malloc (count);
buf = allocated;
/* Write some stuff into the allocated buffer to simulate
* creating some sort of data
*/
i = 0;
while (i < count)
{
allocated[i] = (char) i;
++i;
}
}
else
{
allocated = NULL;
buf = not_allocated;
}
bytes_written = 0;
while (bytes_written < count)
{
again:
val = write (fd, buf + bytes_written, count - bytes_written);
if (val < 0)
{
if (errno == EINTR)
goto again;
else
{
g_printerr ("write() failed thread %p: %s\n",
g_thread_self(), strerror (errno));
exit (1);
}
}
else
{
bytes_written += val;
}
}
if (fake_malloc_overhead)
g_free (allocated);
#if 0
g_printerr ("%p wrote %d bytes to fd %d\n",
g_thread_self(), bytes_written, fd);
#endif
}
static gboolean
plain_sockets_talk_to_client_watch (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
PlainSocketServer *server = data;
int client_fd = g_io_channel_unix_get_fd (source);
if (condition & G_IO_HUP)
{
g_printerr ("Client disconnected from server\n");
server->sd->n_clients -= 1;
if (server->sd->n_clients == 0)
g_main_loop_quit (server->sd->loop);
return FALSE; /* remove watch */
}
else if (condition & G_IO_IN)
{
server->sd->handled += 1;
read_and_drop_on_floor (client_fd, echo_call_size, server->vtable->fake_malloc_overhead);
write_junk (client_fd, echo_return_size, server->vtable->fake_malloc_overhead);
}
else
{
g_printerr ("Unexpected IO condition in server thread\n");
exit (1);
}
return TRUE;
}
static gboolean
plain_sockets_new_client_watch (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
int client_fd;
struct sockaddr addr;
socklen_t addrlen;
GIOChannel *channel;
PlainSocketServer *server = data;
if (!(condition & G_IO_IN))
{
g_printerr ("Unexpected IO condition on server socket\n");
exit (1);
}
addrlen = sizeof (addr);
retry:
client_fd = accept (server->listen_fd, &addr, &addrlen);
if (client_fd < 0)
{
if (errno == EINTR)
goto retry;
else
{
g_printerr ("Failed to accept() connection from client: %s\n",
strerror (errno));
exit (1);
}
}
channel = g_io_channel_unix_new (client_fd);
g_io_add_watch (channel,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_PRI,
plain_sockets_talk_to_client_watch,
server);
g_io_channel_unref (channel);
server->sd->n_clients += 1;
return TRUE;
}
static void*
plain_sockets_init_server (ServerData *sd)
{
PlainSocketServer *server;
struct sockaddr_un addr;
static char path[] = "/tmp/dbus-test-profile-XXXXXX";
char *p;
GIOChannel *channel;
server = g_new0 (PlainSocketServer, 1);
server->sd = sd;
server->vtable = sd->vtable; /* for convenience */
p = path;
while (*p)
{
if (*p == 'X')
*p = 'a' + (int) (26.0*rand()/(RAND_MAX+1.0));
++p;
}
g_printerr ("Socket is %s\n", path);
server->listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (server->listen_fd < 0)
{
g_printerr ("Failed to create socket: %s",
strerror (errno));
exit (1);
}
_DBUS_ZERO (addr);
addr.sun_family = AF_UNIX;
#ifdef HAVE_ABSTRACT_SOCKETS
/* remember that abstract names aren't nul-terminated so we rely
* on sun_path being filled in with zeroes above.
*/
addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
/* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
#else /* HAVE_ABSTRACT_SOCKETS */
{
struct stat sb;
if (stat (path, &sb) == 0 &&
S_ISSOCK (sb.st_mode))
unlink (path);
}
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
#endif /* ! HAVE_ABSTRACT_SOCKETS */
if (bind (server->listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
{
g_printerr ("Failed to bind socket \"%s\": %s",
path, strerror (errno));
exit (1);
}
if (listen (server->listen_fd, 30 /* backlog */) < 0)
{
g_printerr ("Failed to listen on socket \"%s\": %s",
path, strerror (errno));
exit (1);
}
plain_sockets_address = path;
channel = g_io_channel_unix_new (server->listen_fd);
server->source_id =
g_io_add_watch (channel,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_PRI,
plain_sockets_new_client_watch,
server);
g_io_channel_unref (channel);
return server;
}
static void
plain_sockets_stop_server (ServerData *sd,
void *server_v)
{
PlainSocketServer *server = server_v;
g_source_remove (server->source_id);
close (server->listen_fd);
g_free (server);
{
struct stat sb;
if (stat (plain_sockets_address, &sb) == 0 &&
S_ISSOCK (sb.st_mode))
unlink (plain_sockets_address);
}
}
static gboolean
plain_sockets_client_side_watch (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
ClientData *cd = data;
int fd = g_io_channel_unix_get_fd (source);
if (condition & G_IO_IN)
{
read_and_drop_on_floor (fd, echo_return_size, cd->vtable->fake_malloc_overhead);
}
else if (condition & G_IO_OUT)
{
cd->iterations += 1;
if (cd->iterations >= N_ITERATIONS)
{
g_printerr ("\nCompleted %d iterations\n", N_ITERATIONS);
g_main_loop_quit (cd->loop);
}
else if (cd->iterations % (N_ITERATIONS/N_PROGRESS_UPDATES) == 0)
{
g_printerr ("%d%% ", (int) (cd->iterations/(double)N_ITERATIONS * 100.0));
}
write_junk (fd, echo_call_size, cd->vtable->fake_malloc_overhead);
}
else
{
g_printerr ("Unexpected IO condition in client thread\n");
exit (1);
}
return TRUE;
}
static void*
plain_sockets_thread_func (void *data)
{
GMainContext *context;
ClientData cd;
int fd;
struct sockaddr_un addr;
GIOChannel *channel;
GSource *gsource;
g_printerr ("Starting client thread %p\n",
g_thread_self());
fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
{
g_printerr ("Failed to create socket: %s",
strerror (errno));
exit (1);
}
_DBUS_ZERO (addr);
addr.sun_family = AF_UNIX;
#ifdef HAVE_ABSTRACT_SOCKETS
/* remember that abstract names aren't nul-terminated so we rely
* on sun_path being filled in with zeroes above.
*/
addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
strncpy (&addr.sun_path[1], plain_sockets_address, _DBUS_MAX_SUN_PATH_LENGTH - 2);
/* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
#else /* HAVE_ABSTRACT_SOCKETS */
strncpy (addr.sun_path, plain_sockets_address, _DBUS_MAX_SUN_PATH_LENGTH - 1);
#endif /* ! HAVE_ABSTRACT_SOCKETS */
if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
{
g_printerr ("Failed to connect to socket %s: %s",
plain_sockets_address, strerror (errno));
exit (1);
}
context = g_main_context_new ();
cd.iterations = 1;
cd.loop = g_main_loop_new (context, FALSE);
channel = g_io_channel_unix_new (fd);
gsource = g_io_create_watch (channel,
G_IO_IN | G_IO_OUT |
G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_PRI);
g_source_set_callback (gsource,
(GSourceFunc)plain_sockets_client_side_watch,
&cd, NULL);
g_source_attach (gsource, context);
g_io_channel_unref (channel);
g_printerr ("Client thread writing to prime pingpong\n");
write_junk (fd, echo_call_size, cd.vtable->fake_malloc_overhead);
g_printerr ("Client thread done writing primer\n");
g_printerr ("Client thread entering main loop\n");
g_main_loop_run (cd.loop);
g_printerr ("Client thread %p exiting main loop\n",
g_thread_self());
g_source_destroy (gsource);
close (fd);
g_main_loop_unref (cd.loop);
g_main_context_unref (context);
return NULL;
}
static void
plain_sockets_main_loop_run (GMainLoop *loop)
{
g_main_loop_run (loop);
}
static const ProfileRunVTable plain_sockets_vtable = {
"plain sockets",
FALSE,
plain_sockets_init_server,
plain_sockets_stop_server,
plain_sockets_thread_func,
plain_sockets_main_loop_run
};
static const ProfileRunVTable plain_sockets_with_malloc_vtable = {
"plain sockets with malloc overhead",
TRUE,
plain_sockets_init_server,
plain_sockets_stop_server,
plain_sockets_thread_func,
plain_sockets_main_loop_run
};
2004-11-25 Havoc Pennington <hp@redhat.com> The primary change here is to always write() once before adding the write watch, which gives us about a 10% performance increase. * dbus/dbus-transport-unix.c: a number of modifications to cope with removing messages_pending (check_write_watch): properly handle DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of messages_pending stuff (check_read_watch): properly handle WAITING_FOR_MEMORY and AUTHENTICATED cases (unix_handle_watch): after writing, see if the write watch can be removed (unix_do_iteration): assert that write_watch/read_watch are non-NULL rather than testing that they aren't, since they aren't allowed to be NULL. check_write_watch() at the end so we add the watch if we did not finish writing (e.g. got EAGAIN) * dbus/dbus-transport-protected.h: remove messages_pending call, since it resulted in too much inefficient watch adding/removing; instead we now require that the transport user does an iteration after queueing outgoing messages, and after trying the first write() we add a write watch if we got EAGAIN or exceeded our max bytes to write per iteration setting * dbus/dbus-string.c (_dbus_string_validate_signature): add this function * dbus/dbus-server-unix.c (unix_finalize): the socket name was freed and then accessed, valgrind flagged this bug, fix it * dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken as the last valid field plus 1, where really it is equal to the last valid field. Corrects some message corruption issues. * dbus/dbus-mainloop.c: verbosity changes * dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM instead of aborting in one of the test codepaths * dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that caused not printing the pid ever again if a verbose was missing the newline at the end (_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE * dbus/dbus-connection.c: verbosity changes; (dbus_connection_has_messages_to_send): new function (_dbus_connection_message_sent): no longer call transport->messages_pending (_dbus_connection_send_preallocated_unlocked): do one iteration to try to write() immediately, so we can avoid the write watch. This is the core purpose of this patchset (_dbus_connection_get_dispatch_status_unlocked): if disconnected, dump the outgoing message queue, so nobody will get confused trying to send them or thinking stuff is pending to be sent * bus/test.c: verbosity changes * bus/driver.c: verbosity/assertion changes * bus/dispatch.c: a bunch of little tweaks to get it working again because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
static double
do_profile_run (const ProfileRunVTable *vtable)
{
GTimer *timer;
int i;
double secs;
ServerData sd;
void *server;
g_printerr ("Profiling %s\n", vtable->name);
sd.handled = 0;
sd.n_clients = 0;
sd.loop = g_main_loop_new (NULL, FALSE);
sd.vtable = vtable;
2003-09-30 02:43:21 +00:00
server = (* vtable->init_server) (&sd);
2003-09-30 02:43:21 +00:00
for (i = 0; i < N_CLIENT_THREADS; i++)
{
g_thread_create (vtable->client_thread_func, (void*) vtable, FALSE, NULL);
2003-09-30 02:43:21 +00:00
}
timer = g_timer_new ();
g_printerr ("Server thread %p entering main loop\n",
g_thread_self());
(* vtable->main_loop_run_func) (sd.loop);
g_printerr ("Server thread %p exiting main loop\n",
g_thread_self());
2003-09-30 02:43:21 +00:00
secs = g_timer_elapsed (timer, NULL);
g_timer_destroy (timer);
g_printerr ("%s: %g seconds, %d round trips, %f seconds per pingpong\n",
vtable->name, secs, sd.handled, secs/sd.handled);
(* vtable->stop_server) (&sd, server);
2003-09-30 02:43:21 +00:00
g_main_loop_unref (sd.loop);
2004-11-25 Havoc Pennington <hp@redhat.com> The primary change here is to always write() once before adding the write watch, which gives us about a 10% performance increase. * dbus/dbus-transport-unix.c: a number of modifications to cope with removing messages_pending (check_write_watch): properly handle DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of messages_pending stuff (check_read_watch): properly handle WAITING_FOR_MEMORY and AUTHENTICATED cases (unix_handle_watch): after writing, see if the write watch can be removed (unix_do_iteration): assert that write_watch/read_watch are non-NULL rather than testing that they aren't, since they aren't allowed to be NULL. check_write_watch() at the end so we add the watch if we did not finish writing (e.g. got EAGAIN) * dbus/dbus-transport-protected.h: remove messages_pending call, since it resulted in too much inefficient watch adding/removing; instead we now require that the transport user does an iteration after queueing outgoing messages, and after trying the first write() we add a write watch if we got EAGAIN or exceeded our max bytes to write per iteration setting * dbus/dbus-string.c (_dbus_string_validate_signature): add this function * dbus/dbus-server-unix.c (unix_finalize): the socket name was freed and then accessed, valgrind flagged this bug, fix it * dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken as the last valid field plus 1, where really it is equal to the last valid field. Corrects some message corruption issues. * dbus/dbus-mainloop.c: verbosity changes * dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM instead of aborting in one of the test codepaths * dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that caused not printing the pid ever again if a verbose was missing the newline at the end (_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE * dbus/dbus-connection.c: verbosity changes; (dbus_connection_has_messages_to_send): new function (_dbus_connection_message_sent): no longer call transport->messages_pending (_dbus_connection_send_preallocated_unlocked): do one iteration to try to write() immediately, so we can avoid the write watch. This is the core purpose of this patchset (_dbus_connection_get_dispatch_status_unlocked): if disconnected, dump the outgoing message queue, so nobody will get confused trying to send them or thinking stuff is pending to be sent * bus/test.c: verbosity changes * bus/driver.c: verbosity/assertion changes * bus/dispatch.c: a bunch of little tweaks to get it working again because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
return secs;
}
static void
print_result (const ProfileRunVTable *vtable,
double seconds,
double baseline)
{
g_printerr (" %g times slower for %s (%g seconds, %f per iteration)\n",
seconds/baseline, vtable->name,
seconds, seconds / N_ITERATIONS);
}
int
main (int argc, char *argv[])
{
g_thread_init (NULL);
dbus_g_thread_init ();
2005-01-15 Havoc Pennington <hp@redhat.com> * Land the new message args API and type system. This patch is huge, but the public API change is not really large. The set of D-BUS types has changed somewhat, and the arg "getters" are more geared toward language bindings; they don't make a copy, etc. There are also some known issues. See these emails for details on this huge patch: http://lists.freedesktop.org/archives/dbus/2004-December/001836.html http://lists.freedesktop.org/archives/dbus/2005-January/001922.html * dbus/dbus-marshal-*: all the new stuff * dbus/dbus-message.c: basically rewritten * dbus/dbus-memory.c (check_guards): with "guards" enabled, init freed blocks to be all non-nul bytes so using freed memory is less likely to work right * dbus/dbus-internals.c (_dbus_test_oom_handling): add DBUS_FAIL_MALLOC=N environment variable, so you can do DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or DBUS_FAIL_MALLOC=10 to make it really, really, really slow and thorough. * qt/message.cpp: port to the new message args API (operator<<): use str.utf8() rather than str.unicode() (pretty sure this is right from the Qt docs?) * glib/dbus-gvalue.c: port to the new message args API * bus/dispatch.c, bus/driver.c: port to the new message args API * dbus/dbus-string.c (_dbus_string_init_const_len): initialize the "locked" flag to TRUE and align_offset to 0; I guess we never looked at these anyhow, but seems cleaner. * dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING): move allocation padding macro to this header; use it to implement (_DBUS_STRING_STATIC): ability to declare a static string. * dbus/dbus-message.c (_dbus_message_has_type_interface_member): change to return TRUE if the interface is not set. * dbus/dbus-string.[hc]: move the D-BUS specific validation stuff to dbus-marshal-validate.[hc] * dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from dbus-internals.c * dbus/Makefile.am: cut over from dbus-marshal.[hc] to dbus-marshal-*.[hc] * dbus/dbus-object-tree.c (_dbus_decompose_path): move this function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
#ifndef DBUS_DISABLE_ASSERT
g_printerr ("You should probably --disable-asserts before you profile as they have noticeable overhead\n");
#endif
#if DBUS_ENABLE_VERBOSE_MODE
g_printerr ("You should probably --disable-verbose-mode before you profile as verbose has noticeable overhead\n");
#endif
payload = g_malloc (PAYLOAD_SIZE);
/* The actual size of the DBusMessage on the wire, as of Nov 23 2004,
* without the payload
*/
echo_call_size = 140 + PAYLOAD_SIZE;
echo_return_size = 32;
if (argc > 1 && strcmp (argv[1], "plain_sockets") == 0)
do_profile_run (&plain_sockets_vtable);
else if (argc > 1 && strcmp (argv[1], "plain_sockets_with_malloc") == 0)
do_profile_run (&plain_sockets_with_malloc_vtable);
else if (argc > 1 && strcmp (argv[1], "no_bus") == 0)
do_profile_run (&no_bus_vtable);
else if (argc > 1 && strcmp (argv[1], "with_bus") == 0)
do_profile_run (&with_bus_vtable);
else if (argc > 1 && strcmp (argv[1], "all") == 0)
{
double e1, e2, e3, e4;
2004-11-25 Havoc Pennington <hp@redhat.com> The primary change here is to always write() once before adding the write watch, which gives us about a 10% performance increase. * dbus/dbus-transport-unix.c: a number of modifications to cope with removing messages_pending (check_write_watch): properly handle DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of messages_pending stuff (check_read_watch): properly handle WAITING_FOR_MEMORY and AUTHENTICATED cases (unix_handle_watch): after writing, see if the write watch can be removed (unix_do_iteration): assert that write_watch/read_watch are non-NULL rather than testing that they aren't, since they aren't allowed to be NULL. check_write_watch() at the end so we add the watch if we did not finish writing (e.g. got EAGAIN) * dbus/dbus-transport-protected.h: remove messages_pending call, since it resulted in too much inefficient watch adding/removing; instead we now require that the transport user does an iteration after queueing outgoing messages, and after trying the first write() we add a write watch if we got EAGAIN or exceeded our max bytes to write per iteration setting * dbus/dbus-string.c (_dbus_string_validate_signature): add this function * dbus/dbus-server-unix.c (unix_finalize): the socket name was freed and then accessed, valgrind flagged this bug, fix it * dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken as the last valid field plus 1, where really it is equal to the last valid field. Corrects some message corruption issues. * dbus/dbus-mainloop.c: verbosity changes * dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM instead of aborting in one of the test codepaths * dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that caused not printing the pid ever again if a verbose was missing the newline at the end (_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE * dbus/dbus-connection.c: verbosity changes; (dbus_connection_has_messages_to_send): new function (_dbus_connection_message_sent): no longer call transport->messages_pending (_dbus_connection_send_preallocated_unlocked): do one iteration to try to write() immediately, so we can avoid the write watch. This is the core purpose of this patchset (_dbus_connection_get_dispatch_status_unlocked): if disconnected, dump the outgoing message queue, so nobody will get confused trying to send them or thinking stuff is pending to be sent * bus/test.c: verbosity changes * bus/driver.c: verbosity/assertion changes * bus/dispatch.c: a bunch of little tweaks to get it working again because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
e1 = do_profile_run (&plain_sockets_vtable);
e2 = do_profile_run (&plain_sockets_with_malloc_vtable);
e3 = do_profile_run (&no_bus_vtable);
e4 = do_profile_run (&with_bus_vtable);
g_printerr ("Baseline plain sockets time %g seconds for %d iterations\n",
e1, N_ITERATIONS);
print_result (&plain_sockets_vtable, e1, e1);
print_result (&plain_sockets_with_malloc_vtable, e2, e1);
print_result (&no_bus_vtable, e3, e1);
print_result (&with_bus_vtable, e4, e1);
2004-11-25 Havoc Pennington <hp@redhat.com> The primary change here is to always write() once before adding the write watch, which gives us about a 10% performance increase. * dbus/dbus-transport-unix.c: a number of modifications to cope with removing messages_pending (check_write_watch): properly handle DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of messages_pending stuff (check_read_watch): properly handle WAITING_FOR_MEMORY and AUTHENTICATED cases (unix_handle_watch): after writing, see if the write watch can be removed (unix_do_iteration): assert that write_watch/read_watch are non-NULL rather than testing that they aren't, since they aren't allowed to be NULL. check_write_watch() at the end so we add the watch if we did not finish writing (e.g. got EAGAIN) * dbus/dbus-transport-protected.h: remove messages_pending call, since it resulted in too much inefficient watch adding/removing; instead we now require that the transport user does an iteration after queueing outgoing messages, and after trying the first write() we add a write watch if we got EAGAIN or exceeded our max bytes to write per iteration setting * dbus/dbus-string.c (_dbus_string_validate_signature): add this function * dbus/dbus-server-unix.c (unix_finalize): the socket name was freed and then accessed, valgrind flagged this bug, fix it * dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken as the last valid field plus 1, where really it is equal to the last valid field. Corrects some message corruption issues. * dbus/dbus-mainloop.c: verbosity changes * dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM instead of aborting in one of the test codepaths * dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that caused not printing the pid ever again if a verbose was missing the newline at the end (_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE * dbus/dbus-connection.c: verbosity changes; (dbus_connection_has_messages_to_send): new function (_dbus_connection_message_sent): no longer call transport->messages_pending (_dbus_connection_send_preallocated_unlocked): do one iteration to try to write() immediately, so we can avoid the write watch. This is the core purpose of this patchset (_dbus_connection_get_dispatch_status_unlocked): if disconnected, dump the outgoing message queue, so nobody will get confused trying to send them or thinking stuff is pending to be sent * bus/test.c: verbosity changes * bus/driver.c: verbosity/assertion changes * bus/dispatch.c: a bunch of little tweaks to get it working again because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
}
else
{
g_printerr ("Specify profile type plain_sockets, plain_sockets_with_malloc, no_bus, with_bus, all\n");
exit (1);
}
/* Make valgrind happy */
dbus_shutdown ();
2003-09-30 02:43:21 +00:00
return 0;
}