summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-08-15 23:10:12 +0000
committerHavoc Pennington <hp@redhat.com>2003-08-15 23:10:12 +0000
commita1b0bd33408f03894987ac32b4e6b46c6a15a594 (patch)
tree2903a89983ce0efa1d3480b5d76322a325e621da
parentef614207fc4f03e5cc02faeb109f739eb1ccdf31 (diff)
downloaddbus-a1b0bd33408f03894987ac32b4e6b46c6a15a594.tar.gz
2003-08-15 Havoc Pennington <hp@redhat.com>
* dbus/dbus-pending-call.c (dbus_pending_call_block): implement * dbus/dbus-connection.c (dbus_connection_send_with_reply_and_block): factor out internals; change to convert any error replies to DBusError instead of returning them as a message
-rw-r--r--ChangeLog9
-rw-r--r--dbus/dbus-connection-internal.h9
-rw-r--r--dbus/dbus-connection.c161
-rw-r--r--dbus/dbus-pending-call.c25
-rw-r--r--dbus/dbus-pending-call.h1
-rw-r--r--glib/dbus-gproxy.h70
6 files changed, 191 insertions, 84 deletions
diff --git a/ChangeLog b/ChangeLog
index f1024dbb..4a8f4ac6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2003-08-15 Havoc Pennington <hp@redhat.com>
+
+ * dbus/dbus-pending-call.c (dbus_pending_call_block): implement
+
+ * dbus/dbus-connection.c
+ (dbus_connection_send_with_reply_and_block): factor out internals;
+ change to convert any error replies to DBusError instead of
+ returning them as a message
+
2003-08-15 Havoc Pennington <hp@pobox.com>
* dbus/dbus-connection.c,
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
index d9d5c5b4..f26c92e6 100644
--- a/dbus/dbus-connection-internal.h
+++ b/dbus/dbus-connection-internal.h
@@ -88,15 +88,18 @@ DBusHandlerResult _dbus_message_handler_handle_message (DBusMessageHandl
DBusMessage *message);
void _dbus_connection_init_id (DBusConnection *connection,
DBusObjectID *id);
-
DBusPendingCall* _dbus_pending_call_new (DBusConnection *connection,
int timeout_milliseconds,
DBusTimeoutHandler timeout_handler);
-
void _dbus_pending_call_notify (DBusPendingCall *pending);
-
void _dbus_connection_remove_pending_call (DBusConnection *connection,
DBusPendingCall *pending);
+DBusMessage* _dbus_connection_block_for_reply (DBusConnection *connection,
+ dbus_uint32_t client_serial,
+ int timeout_milliseconds);
+void _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
+ DBusMessage *message);
+
/**
* @addtogroup DBusPendingCallInternals DBusPendingCall implementation details
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 3af00ed0..bc26a3ec 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -621,6 +621,38 @@ _dbus_connection_remove_pending_call (DBusConnection *connection,
}
/**
+ * Completes a pending call with the given message,
+ * or if the message is #NULL, by timing out the pending call.
+ *
+ * @param pending the pending call
+ * @param message the message to complete the call with, or #NULL
+ * to time out the call
+ */
+void
+_dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
+ DBusMessage *message)
+{
+ if (message == NULL)
+ {
+ message = pending->timeout_link->data;
+ _dbus_list_clear (&pending->timeout_link);
+ }
+
+ _dbus_verbose (" handing message %p to pending call\n", message);
+
+ _dbus_assert (pending->reply == NULL);
+ pending->reply = message;
+ dbus_message_ref (pending->reply);
+
+ dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
+ _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
+
+ /* Must be called unlocked since it invokes app callback */
+ _dbus_pending_call_notify (pending);
+ dbus_pending_call_unref (pending);
+}
+
+/**
* Acquire the transporter I/O path. This must be done before
* doing any I/O in the transporter. May sleep and drop the
* connection mutex while waiting for the I/O path.
@@ -1745,42 +1777,31 @@ check_for_reply_unlocked (DBusConnection *connection,
}
/**
- * Sends a message and blocks a certain time period while waiting for a reply.
- * This function does not dispatch any message handlers until the main loop
- * has been reached. This function is used to do non-reentrant "method calls."
- * If a reply is received, it is returned, and removed from the incoming
- * message queue. If it is not received, #NULL is returned and the
- * error is set to #DBUS_ERROR_NO_REPLY. If something else goes
- * wrong, result is set to whatever is appropriate, such as
- * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED.
+ * Blocks a certain time period while waiting for a reply.
+ * If no reply arrives, returns #NULL.
*
* @todo could use performance improvements (it keeps scanning
* the whole message queue for example) and has thread issues,
* see comments in source
*
* @param connection the connection
- * @param message the message to send
+ * @param client_serial the reply serial to wait for
* @param timeout_milliseconds timeout in milliseconds or -1 for default
- * @param error return location for error message
- * @returns the message that is the reply or #NULL with an error code if the
- * function fails.
+ * @returns the message that is the reply or #NULL if no reply
*/
-DBusMessage *
-dbus_connection_send_with_reply_and_block (DBusConnection *connection,
- DBusMessage *message,
- int timeout_milliseconds,
- DBusError *error)
+DBusMessage*
+_dbus_connection_block_for_reply (DBusConnection *connection,
+ dbus_uint32_t client_serial,
+ int timeout_milliseconds)
{
- dbus_uint32_t client_serial;
long start_tv_sec, start_tv_usec;
long end_tv_sec, end_tv_usec;
long tv_sec, tv_usec;
DBusDispatchStatus status;
_dbus_return_val_if_fail (connection != NULL, NULL);
- _dbus_return_val_if_fail (message != NULL, NULL);
- _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
- _dbus_return_val_if_error_is_set (error, NULL);
+ _dbus_return_val_if_fail (client_serial != 0, NULL);
+ _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
if (timeout_milliseconds == -1)
timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
@@ -1792,14 +1813,6 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
- if (!dbus_connection_send (connection, message, &client_serial))
- {
- _DBUS_SET_OOM (error);
- return NULL;
- }
-
- message = NULL;
-
/* Flush message queue */
dbus_connection_flush (connection);
@@ -1894,11 +1907,6 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
(tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
-
- if (dbus_connection_get_is_connected (connection))
- dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
- else
- dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
/* unlocks and calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
@@ -1907,6 +1915,70 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
}
/**
+ * Sends a message and blocks a certain time period while waiting for
+ * a reply. This function does not reenter the main loop,
+ * i.e. messages other than the reply are queued up but not
+ * processed. This function is used to do non-reentrant "method
+ * calls."
+ *
+ * If a normal reply is received, it is returned, and removed from the
+ * incoming message queue. If it is not received, #NULL is returned
+ * and the error is set to #DBUS_ERROR_NO_REPLY. If an error reply is
+ * received, it is converted to a #DBusError and returned as an error,
+ * then the reply message is deleted. If something else goes wrong,
+ * result is set to whatever is appropriate, such as
+ * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED.
+ *
+ * @param connection the connection
+ * @param message the message to send
+ * @param timeout_milliseconds timeout in milliseconds or -1 for default
+ * @param error return location for error message
+ * @returns the message that is the reply or #NULL with an error code if the
+ * function fails.
+ */
+DBusMessage *
+dbus_connection_send_with_reply_and_block (DBusConnection *connection,
+ DBusMessage *message,
+ int timeout_milliseconds,
+ DBusError *error)
+{
+ dbus_uint32_t client_serial;
+ DBusMessage *reply;
+
+ _dbus_return_val_if_fail (connection != NULL, NULL);
+ _dbus_return_val_if_fail (message != NULL, NULL);
+ _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
+ _dbus_return_val_if_error_is_set (error, NULL);
+
+ if (!dbus_connection_send (connection, message, &client_serial))
+ {
+ _DBUS_SET_OOM (error);
+ return NULL;
+ }
+
+ reply = _dbus_connection_block_for_reply (connection,
+ client_serial,
+ timeout_milliseconds);
+
+ if (reply == NULL)
+ {
+ if (dbus_connection_get_is_connected (connection))
+ dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
+ else
+ dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
+
+ return NULL;
+ }
+ else if (dbus_set_error_from_message (error, reply))
+ {
+ dbus_message_unref (reply);
+ return NULL;
+ }
+ else
+ return reply;
+}
+
+/**
* Blocks until the outgoing message queue is empty.
*
* @param connection the connection.
@@ -2301,6 +2373,10 @@ dbus_connection_get_dispatch_status (DBusConnection *connection)
* be part of authentication or the like.
*
* @todo some FIXME in here about handling DBUS_HANDLER_RESULT_NEED_MEMORY
+ *
+ * @todo right now a message filter gets run on replies to a pending
+ * call in here, but not in the case where we block without
+ * entering the main loop.
*
* @param connection the connection
* @returns dispatch status
@@ -2435,18 +2511,7 @@ dbus_connection_dispatch (DBusConnection *connection)
if (pending)
{
- _dbus_verbose (" handing message %p to pending call\n", message);
-
- _dbus_assert (pending->reply == NULL);
- pending->reply = message;
- dbus_message_ref (pending->reply);
-
- dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
- _dbus_connection_detach_pending_call_and_unlock (connection, pending);
-
- /* Must be called unlocked since it invokes app callback */
- _dbus_pending_call_notify (pending);
- dbus_pending_call_unref (pending);
+ _dbus_pending_call_complete_and_unlock (pending, message);
pending = NULL;
@@ -2869,6 +2934,10 @@ dbus_connection_set_unix_user_function (DBusConnection *connection,
* forgets about it. Thus the caller of this function must keep a
* reference to the message handler.
*
+ * @todo we don't run filters on messages while blocking without
+ * entering the main loop, since filters are run as part of
+ * dbus_connection_dispatch().
+ *
* @param connection the connection
* @param handler the handler
* @returns #TRUE on success, #FALSE if not enough memory.
diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c
index 84ca7ae0..2b6021e9 100644
--- a/dbus/dbus-pending-call.c
+++ b/dbus/dbus-pending-call.c
@@ -254,6 +254,31 @@ dbus_pending_call_get_reply (DBusPendingCall *pending)
return pending->reply;
}
+/**
+ * Block until the pending call is completed. The blocking is as with
+ * dbus_connection_send_with_reply_and_block(); it does not enter the
+ * main loop or process other messages, it simply waits for the reply
+ * in question.
+ *
+ * @todo when you start blocking, the timeout is reset, but it should
+ * really only use time remaining since the pending call was created.
+ *
+ * @param pending the pending call
+ */
+void
+dbus_pending_call_block (DBusPendingCall *pending)
+{
+ DBusMessage *message;
+
+ message = _dbus_connection_block_for_reply (pending->connection,
+ pending->reply_serial,
+ dbus_timeout_get_interval (pending->timeout));
+
+ _dbus_connection_lock (pending->connection);
+ _dbus_pending_call_complete_and_unlock (pending, message);
+ dbus_message_unref (message);
+}
+
/** @} */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-pending-call.h b/dbus/dbus-pending-call.h
index 66f1bac5..81af872f 100644
--- a/dbus/dbus-pending-call.h
+++ b/dbus/dbus-pending-call.h
@@ -42,6 +42,7 @@ void dbus_pending_call_set_notify (DBusPendingCall *pen
void dbus_pending_call_cancel (DBusPendingCall *pending);
dbus_bool_t dbus_pending_call_get_completed (DBusPendingCall *pending);
DBusMessage* dbus_pending_call_get_reply (DBusPendingCall *pending);
+void dbus_pending_call_block (DBusPendingCall *pending);
DBUS_END_DECLS;
diff --git a/glib/dbus-gproxy.h b/glib/dbus-gproxy.h
index bebcd1ce..47b70f36 100644
--- a/glib/dbus-gproxy.h
+++ b/glib/dbus-gproxy.h
@@ -34,43 +34,43 @@
G_BEGIN_DECLS
typedef struct DBusGProxy DBusGProxy;
-typedef struct DBusGPendingCall DBusGPendingCall;
+typedef struct DBusPendingCall DBusPendingCall;
-DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection,
- const char *service_name,
- const char *interface_name);
-DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection,
- const char *service_name,
- const char *interface_name,
- GError **error);
-DBusGProxy* dbus_gproxy_new_for_object_id (DBusConnection *connection,
- const DBusObjectID *object_id,
- const char *interface_name);
-DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection,
- const char *interface_name);
-void dbus_gproxy_ref (DBusGProxy *proxy);
-void dbus_gproxy_unref (DBusGProxy *proxy);
-gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy,
- const char *signal_name,
- GCallback callback,
- void *data,
- GFreeFunc free_data_func,
- GError **error);
-DBusGPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy,
- const char *method,
- int first_arg_type,
- ...);
-void dbus_gproxy_oneway_call (DBusGProxy *proxy,
- const char *method,
- int first_arg_type,
- ...);
+DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection,
+ const char *service_name,
+ const char *interface_name);
+DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection,
+ const char *service_name,
+ const char *interface_name,
+ GError **error);
+DBusGProxy* dbus_gproxy_new_for_object_id (DBusConnection *connection,
+ const DBusObjectID *object_id,
+ const char *interface_name);
+DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection,
+ const char *interface_name);
+void dbus_gproxy_ref (DBusGProxy *proxy);
+void dbus_gproxy_unref (DBusGProxy *proxy);
+gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy,
+ const char *signal_name,
+ GCallback callback,
+ void *data,
+ GFreeFunc free_data_func,
+ GError **error);
+DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy,
+ const char *method,
+ int first_arg_type,
+ ...);
+void dbus_gproxy_oneway_call (DBusGProxy *proxy,
+ const char *method,
+ int first_arg_type,
+ ...);
+gboolean dbus_pending_call_is_complete (DBusPendingCall *call);
+void dbus_pending_call_cancel_and_free (DBusPendingCall *call);
+gboolean dbus_pending_call_block_and_free (DBusPendingCall *call,
+ GError **error,
+ int first_arg_type,
+ ...);
-gboolean dbus_gpending_call_is_complete (DBusGPendingCall *call);
-void dbus_gpending_call_cancel_and_free (DBusGPendingCall *call);
-gboolean dbus_gpending_call_block_and_free (DBusGPendingCall *call,
- GError **error,
- int first_arg_type,
- ...);