From b4a1100f4f81534e2aac0141afda750f318223d4 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 17 Mar 2003 01:54:37 +0000 Subject: 2003-03-16 Havoc Pennington * dbus/dbus-watch.c (_dbus_watch_new): handle failure to malloc the watch * dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new): add some missing dbus_set_result * bus/dispatch.c (bus_dispatch_add_connection): handle failure to alloc the DBusMessageHandler * dbus/dbus-transport.c (_dbus_transport_disconnect): don't ref the transport here, since we call this from the finalizer; it resulted in a double-finalize. * dbus/dbus-transport.c (_dbus_transport_disconnect): fix a bug where we tried to use transport->connection that was NULL, happened when transport was disconnected early on due to OOM * bus/*.c: adapt to handle OOM for watches/timeouts * dbus/dbus-transport-unix.c: port to handle OOM during watch handling * dbus/dbus-auth.c (_dbus_auth_get_unused_bytes): return a reference to unused bytes instead of a copy * dbus/dbus-server.c (dbus_server_handle_watch): return FALSE for out of memory * dbus/dbus-connection.c (dbus_connection_handle_watch): return FALSE on OOM * dbus/dbus-timeout.c (dbus_timeout_handle): return FALSE for out of memory --- dbus/dbus-auth-script.c | 46 +++--- dbus/dbus-auth.c | 82 ++++++---- dbus/dbus-auth.h | 58 +++---- dbus/dbus-connection.c | 22 ++- dbus/dbus-connection.h | 4 +- dbus/dbus-server-debug-pipe.c | 8 +- dbus/dbus-server-debug.c | 11 +- dbus/dbus-server-protected.h | 10 +- dbus/dbus-server-unix.c | 19 ++- dbus/dbus-server.c | 11 +- dbus/dbus-server.h | 2 +- dbus/dbus-sysdeps.c | 3 +- dbus/dbus-timeout.c | 11 +- dbus/dbus-timeout.h | 2 +- dbus/dbus-transport-debug.c | 36 +++-- dbus/dbus-transport-protected.h | 24 +-- dbus/dbus-transport-unix.c | 340 +++++++++++++++++----------------------- dbus/dbus-transport.c | 128 ++++++++++++++- dbus/dbus-transport.h | 2 +- dbus/dbus-watch.c | 3 + 20 files changed, 477 insertions(+), 345 deletions(-) (limited to 'dbus') diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c index 336d63e1..d954c8dd 100644 --- a/dbus/dbus-auth-script.c +++ b/dbus/dbus-auth-script.c @@ -437,14 +437,23 @@ _dbus_auth_script_run (const DBusString *filename) _dbus_string_free (&username); } } - - if (!_dbus_auth_bytes_received (auth, &to_send)) - { - _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n"); - _dbus_string_free (&to_send); - goto out; - } + { + DBusString *buffer; + + _dbus_auth_get_buffer (auth, &buffer); + if (!_dbus_string_copy (&to_send, 0, + buffer, _dbus_string_get_length (buffer))) + { + _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n"); + _dbus_string_free (&to_send); + _dbus_auth_return_buffer (auth, buffer, 0); + goto out; + } + + _dbus_auth_return_buffer (auth, buffer, _dbus_string_get_length (&to_send)); + } + _dbus_string_free (&to_send); } else if (_dbus_string_starts_with_c_str (&line, @@ -510,7 +519,7 @@ _dbus_auth_script_run (const DBusString *filename) "EXPECT_UNUSED")) { DBusString expected; - DBusString unused; + const DBusString *unused; _dbus_string_delete_first_word (&line); @@ -528,35 +537,20 @@ _dbus_auth_script_run (const DBusString *filename) goto out; } - if (!_dbus_string_init (&unused, _DBUS_INT_MAX)) - { - _dbus_warn ("no mem to allocate string unused\n"); - _dbus_string_free (&expected); - goto out; - } - - if (!_dbus_auth_get_unused_bytes (auth, &unused)) - { - _dbus_warn ("couldn't get unused bytes\n"); - _dbus_string_free (&expected); - _dbus_string_free (&unused); - goto out; - } + _dbus_auth_get_unused_bytes (auth, &unused); - if (_dbus_string_equal (&expected, &unused)) + if (_dbus_string_equal (&expected, unused)) { _dbus_string_free (&expected); - _dbus_string_free (&unused); } else { const char *e1, *h1; _dbus_string_get_const_data (&expected, &e1); - _dbus_string_get_const_data (&unused, &h1); + _dbus_string_get_const_data (unused, &h1); _dbus_warn ("Expected unused bytes '%s' and have '%s'\n", e1, h1); _dbus_string_free (&expected); - _dbus_string_free (&unused); goto out; } } diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index 4b1f5504..9e2b1d95 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -169,6 +169,7 @@ struct DBusAuth unsigned int authenticated_pending_begin : 1; /**< Authenticated once we get BEGIN */ unsigned int already_got_mechanisms : 1; /**< Client already got mech list */ unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */ + unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */ }; typedef struct @@ -1996,35 +1997,40 @@ _dbus_auth_bytes_sent (DBusAuth *auth, } /** - * Stores bytes received from the peer we're conversing with. + * Get a buffer to be used for reading bytes from the peer we're conversing + * with. Bytes should be appended to this buffer. * * @param auth the auth conversation - * @param str the received bytes. - * @returns #FALSE if not enough memory to store the bytes or we were already authenticated. + * @param buffer return location for buffer to append bytes to */ -dbus_bool_t -_dbus_auth_bytes_received (DBusAuth *auth, - const DBusString *str) +void +_dbus_auth_get_buffer (DBusAuth *auth, + DBusString **buffer) { _dbus_assert (auth != NULL); - _dbus_assert (str != NULL); + _dbus_assert (!auth->buffer_outstanding); - if (DBUS_AUTH_IN_END_STATE (auth)) - return FALSE; + *buffer = &auth->incoming; - auth->needed_memory = FALSE; - - if (!_dbus_string_copy (str, 0, - &auth->incoming, - _dbus_string_get_length (&auth->incoming))) - { - auth->needed_memory = TRUE; - return FALSE; - } + auth->buffer_outstanding = TRUE; +} - _dbus_auth_do_work (auth); - - return TRUE; +/** + * Returns a buffer with new data read into it. + * + * @param auth the auth conversation + * @param buffer the buffer being returned + * @param bytes_read number of new bytes added + */ +void +_dbus_auth_return_buffer (DBusAuth *auth, + DBusString *buffer, + int bytes_read) +{ + _dbus_assert (buffer == &auth->incoming); + _dbus_assert (auth->buffer_outstanding); + + auth->buffer_outstanding = FALSE; } /** @@ -2034,22 +2040,32 @@ _dbus_auth_bytes_received (DBusAuth *auth, * succeeded. * * @param auth the auth conversation - * @param str string to append the unused bytes to - * @returns #FALSE if not enough memory to return the bytes + * @param str return location for pointer to string of unused bytes */ -dbus_bool_t -_dbus_auth_get_unused_bytes (DBusAuth *auth, - DBusString *str) +void +_dbus_auth_get_unused_bytes (DBusAuth *auth, + const DBusString **str) { if (!DBUS_AUTH_IN_END_STATE (auth)) - return FALSE; - - if (!_dbus_string_move (&auth->incoming, - 0, str, - _dbus_string_get_length (str))) - return FALSE; + return; - return TRUE; + *str = &auth->incoming; +} + + +/** + * Gets rid of unused bytes returned by _dbus_auth_get_unused_bytes() + * after we've gotten them and successfully moved them elsewhere. + * + * @param auth the auth conversation + */ +void +_dbus_auth_delete_unused_bytes (DBusAuth *auth) +{ + if (!DBUS_AUTH_IN_END_STATE (auth)) + return; + + _dbus_string_set_length (&auth->incoming, 0); } /** diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h index 0339a4f8..8309fe33 100644 --- a/dbus/dbus-auth.h +++ b/dbus/dbus-auth.h @@ -42,34 +42,38 @@ typedef enum DBUS_AUTH_STATE_AUTHENTICATED } DBusAuthState; -DBusAuth* _dbus_auth_server_new (void); -DBusAuth* _dbus_auth_client_new (void); -void _dbus_auth_ref (DBusAuth *auth); -void _dbus_auth_unref (DBusAuth *auth); -DBusAuthState _dbus_auth_do_work (DBusAuth *auth); -dbus_bool_t _dbus_auth_get_bytes_to_send (DBusAuth *auth, - const DBusString **str); -void _dbus_auth_bytes_sent (DBusAuth *auth, - int bytes_sent); -dbus_bool_t _dbus_auth_bytes_received (DBusAuth *auth, - const DBusString *str); -dbus_bool_t _dbus_auth_get_unused_bytes (DBusAuth *auth, - DBusString *str); -dbus_bool_t _dbus_auth_needs_encoding (DBusAuth *auth); -dbus_bool_t _dbus_auth_encode_data (DBusAuth *auth, - const DBusString *plaintext, - DBusString *encoded); -dbus_bool_t _dbus_auth_needs_decoding (DBusAuth *auth); -dbus_bool_t _dbus_auth_decode_data (DBusAuth *auth, - const DBusString *encoded, - DBusString *plaintext); -void _dbus_auth_set_credentials (DBusAuth *auth, - const DBusCredentials *credentials); +DBusAuth* _dbus_auth_server_new (void); +DBusAuth* _dbus_auth_client_new (void); +void _dbus_auth_ref (DBusAuth *auth); +void _dbus_auth_unref (DBusAuth *auth); +DBusAuthState _dbus_auth_do_work (DBusAuth *auth); +dbus_bool_t _dbus_auth_get_bytes_to_send (DBusAuth *auth, + const DBusString **str); +void _dbus_auth_bytes_sent (DBusAuth *auth, + int bytes_sent); +void _dbus_auth_get_buffer (DBusAuth *auth, + DBusString **buffer); +void _dbus_auth_return_buffer (DBusAuth *auth, + DBusString *buffer, + int bytes_read); +void _dbus_auth_get_unused_bytes (DBusAuth *auth, + const DBusString **str); +void _dbus_auth_delete_unused_bytes (DBusAuth *auth); +dbus_bool_t _dbus_auth_needs_encoding (DBusAuth *auth); +dbus_bool_t _dbus_auth_encode_data (DBusAuth *auth, + const DBusString *plaintext, + DBusString *encoded); +dbus_bool_t _dbus_auth_needs_decoding (DBusAuth *auth); +dbus_bool_t _dbus_auth_decode_data (DBusAuth *auth, + const DBusString *encoded, + DBusString *plaintext); +void _dbus_auth_set_credentials (DBusAuth *auth, + const DBusCredentials *credentials); +void _dbus_auth_get_identity (DBusAuth *auth, + DBusCredentials *credentials); +dbus_bool_t _dbus_auth_set_context (DBusAuth *auth, + const DBusString *context); -void _dbus_auth_get_identity (DBusAuth *auth, - DBusCredentials *credentials); -dbus_bool_t _dbus_auth_set_context (DBusAuth *auth, - const DBusString *context); DBUS_END_DECLS; diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 7f9423af..d6ee104a 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -1166,7 +1166,7 @@ dbus_connection_send (DBusConnection *connection, } } -static void +static dbus_bool_t reply_handler_timeout (void *data) { DBusConnection *connection; @@ -1187,6 +1187,8 @@ reply_handler_timeout (void *data) reply_handler_data->timeout_added = FALSE; dbus_mutex_unlock (connection->mutex); + + return TRUE; } static void @@ -2171,21 +2173,33 @@ dbus_connection_set_wakeup_main_function (DBusConnection *connection, * is ready for reading or writing, or has an exception such * as a hangup. * + * If this function returns #FALSE, then the file descriptor may still + * be ready for reading or writing, but more memory is needed in order + * to do the reading or writing. If you ignore the #FALSE return, your + * application may spin in a busy loop on the file descriptor until + * memory becomes available, but nothing more catastrophic should + * happen. + * * @param connection the connection. * @param watch the watch. * @param condition the current condition of the file descriptors being watched. + * @returns #FALSE if the IO condition may not have been fully handled due to lack of memory */ -void +dbus_bool_t dbus_connection_handle_watch (DBusConnection *connection, DBusWatch *watch, unsigned int condition) { + dbus_bool_t retval; + dbus_mutex_lock (connection->mutex); _dbus_connection_acquire_io_path (connection, -1); - _dbus_transport_handle_watch (connection->transport, - watch, condition); + retval = _dbus_transport_handle_watch (connection->transport, + watch, condition); _dbus_connection_release_io_path (connection); dbus_mutex_unlock (connection->mutex); + + return retval; } /** diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index b4e6007d..9b135a5d 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -120,7 +120,7 @@ void dbus_connection_set_wakeup_main_function (DBusConnection DBusWakeupMainFunction wakeup_main_function, void *data, DBusFreeFunction free_data_function); -void dbus_connection_handle_watch (DBusConnection *connection, +dbus_bool_t dbus_connection_handle_watch (DBusConnection *connection, DBusWatch *watch, unsigned int condition); @@ -138,7 +138,7 @@ void* dbus_timeout_get_data (DBusTimeout *timeout); void dbus_timeout_set_data (DBusTimeout *timeout, void *data, DBusFreeFunction free_data_function); -void dbus_timeout_handle (DBusTimeout *timeout); +dbus_bool_t dbus_timeout_handle (DBusTimeout *timeout); dbus_bool_t dbus_timeout_get_enabled (DBusTimeout *timeout); /* Handlers */ diff --git a/dbus/dbus-server-debug-pipe.c b/dbus/dbus-server-debug-pipe.c index 8f57ae8d..46e78ddd 100644 --- a/dbus/dbus-server-debug-pipe.c +++ b/dbus/dbus-server-debug-pipe.c @@ -73,12 +73,13 @@ debug_finalize (DBusServer *server) dbus_free (server); } -static void +static dbus_bool_t debug_handle_watch (DBusServer *server, DBusWatch *watch, unsigned int flags) { - + + return TRUE; } static void @@ -211,6 +212,7 @@ _dbus_transport_debug_pipe_new (const char *server_name, { _dbus_close (client_fd, NULL); _dbus_close (server_fd, NULL); + dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return NULL; } @@ -222,6 +224,7 @@ _dbus_transport_debug_pipe_new (const char *server_name, { _dbus_transport_unref (client_transport); _dbus_close (server_fd, NULL); + dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return NULL; } @@ -234,6 +237,7 @@ _dbus_transport_debug_pipe_new (const char *server_name, if (connection == NULL) { _dbus_transport_unref (client_transport); + dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return NULL; } diff --git a/dbus/dbus-server-debug.c b/dbus/dbus-server-debug.c index b1318e32..3b7e78dd 100644 --- a/dbus/dbus-server-debug.c +++ b/dbus/dbus-server-debug.c @@ -71,11 +71,12 @@ debug_finalize (DBusServer *server) { } -static void +static dbus_bool_t debug_handle_watch (DBusServer *server, DBusWatch *watch, unsigned int flags) { + return TRUE; } static void @@ -184,7 +185,7 @@ typedef struct DBusTimeout *timeout; } ServerAndTransport; -static void +static dbus_bool_t handle_new_client (void *data) { ServerAndTransport *st = data; @@ -196,13 +197,13 @@ handle_new_client (void *data) transport = _dbus_transport_debug_server_new (st->transport); if (transport == NULL) - return; + return FALSE; connection = _dbus_connection_new_for_transport (transport); _dbus_transport_unref (transport); if (connection == NULL) - return; + return FALSE; /* See if someone wants to handle this new connection, * self-referencing for paranoia @@ -223,6 +224,8 @@ handle_new_client (void *data) /* killing timeout frees both "st" and "timeout" */ _dbus_timeout_unref (st->timeout); + + return TRUE; } /** diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h index bbedeea3..d47215b7 100644 --- a/dbus/dbus-server-protected.h +++ b/dbus/dbus-server-protected.h @@ -36,17 +36,17 @@ typedef struct DBusServerVTable DBusServerVTable; struct DBusServerVTable { - void (* finalize) (DBusServer *server); + void (* finalize) (DBusServer *server); /**< The finalize method must free the server. */ - void (* handle_watch) (DBusServer *server, - DBusWatch *watch, - unsigned int flags); + dbus_bool_t (* handle_watch) (DBusServer *server, + DBusWatch *watch, + unsigned int flags); /**< The handle_watch method handles reading/writing * data as indicated by the flags. */ - void (* disconnect) (DBusServer *server); + void (* disconnect) (DBusServer *server); /**< Disconnect this server. */ }; diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index a181a925..88cc9ed7 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -70,7 +70,8 @@ unix_finalize (DBusServer *server) * us to drop the last ref to the connection before * disconnecting it. That is invalid. */ -static void +/* Return value is just for memory, not other failures. */ +static dbus_bool_t handle_new_client_fd (DBusServer *server, int client_fd) { @@ -80,13 +81,13 @@ handle_new_client_fd (DBusServer *server, _dbus_verbose ("Creating new client connection with fd %d\n", client_fd); if (!_dbus_set_fd_nonblocking (client_fd, NULL)) - return; + return TRUE; transport = _dbus_transport_new_for_fd (client_fd, TRUE); if (transport == NULL) { close (client_fd); - return; + return FALSE; } /* note that client_fd is now owned by the transport, and will be @@ -97,7 +98,7 @@ handle_new_client_fd (DBusServer *server, _dbus_transport_unref (transport); if (connection == NULL) - return; + return FALSE; _dbus_connection_set_connection_counter (connection, server->connection_counter); @@ -116,9 +117,11 @@ handle_new_client_fd (DBusServer *server, /* If no one grabbed a reference, the connection will die. */ dbus_connection_unref (connection); + + return TRUE; } -static void +static dbus_bool_t unix_handle_watch (DBusServer *server, DBusWatch *watch, unsigned int flags) @@ -151,7 +154,9 @@ unix_handle_watch (DBusServer *server, else { _dbus_fd_set_close_on_exec (client_fd); - handle_new_client_fd (server, client_fd); + + if (!handle_new_client_fd (server, client_fd)) + _dbus_verbose ("Rejected client connection due to lack of memory\n"); } } @@ -160,6 +165,8 @@ unix_handle_watch (DBusServer *server, if (flags & DBUS_WATCH_HANGUP) _dbus_verbose ("Hangup on server listening socket\n"); + + return TRUE; } static void diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 79ed7ed4..ba48cd97 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -498,12 +498,19 @@ dbus_server_set_timeout_functions (DBusServer *server, * Called to notify the server when a previously-added watch * is ready for reading or writing, or has an exception such * as a hangup. + * + * If this function returns #FALSE, then the file descriptor may still + * be ready for reading or writing, but more memory is needed in order + * to do the reading or writing. If you ignore the #FALSE return, your + * application may spin in a busy loop on the file descriptor until + * memory becomes available, but nothing more catastrophic should + * happen. * * @param server the server. * @param watch the watch. * @param condition the current condition of the file descriptors being watched. */ -void +dbus_bool_t dbus_server_handle_watch (DBusServer *server, DBusWatch *watch, unsigned int condition) @@ -512,7 +519,7 @@ dbus_server_handle_watch (DBusServer *server, _dbus_watch_sanitize_condition (watch, &condition); - (* server->vtable->handle_watch) (server, watch, condition); + return (* server->vtable->handle_watch) (server, watch, condition); } /** diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h index 589237f1..75632440 100644 --- a/dbus/dbus-server.h +++ b/dbus/dbus-server.h @@ -61,7 +61,7 @@ dbus_bool_t dbus_server_set_timeout_functions (DBusServer * DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function); -void dbus_server_handle_watch (DBusServer *server, +dbus_bool_t dbus_server_handle_watch (DBusServer *server, DBusWatch *watch, unsigned int condition); void dbus_server_set_max_connections (DBusServer *server, diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index e6e0b276..8abcc5fc 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -130,7 +130,8 @@ _dbus_getenv (const char *varname) * the data it reads to the DBusString buffer. It appends * up to the given count, and returns the same value * and same errno as read(). The only exception is that - * _dbus_read() handles EINTR for you. + * _dbus_read() handles EINTR for you. _dbus_read() can + * return ENOMEM, even though regular UNIX read doesn't. * * @param fd the file descriptor to read from * @param buffer the buffer to append data to diff --git a/dbus/dbus-timeout.c b/dbus/dbus-timeout.c index 9825872e..a77363be 100644 --- a/dbus/dbus-timeout.c +++ b/dbus/dbus-timeout.c @@ -405,12 +405,19 @@ dbus_timeout_set_data (DBusTimeout *timeout, * This function should be called when the timeout * occurs. * + * If this function returns #FALSE, then there wasn't + * enough memory to handle the timeout. Typically just + * letting the timeout fire again next time it naturally + * times out is an adequate response to that problem, + * but you could try to do more if you wanted. + * * @param timeout the DBusTimeout object. + * @returns #FALSE if there wasn't enough memory */ -void +dbus_bool_t dbus_timeout_handle (DBusTimeout *timeout) { - (* timeout->handler) (timeout->handler_data); + return (* timeout->handler) (timeout->handler_data); } diff --git a/dbus/dbus-timeout.h b/dbus/dbus-timeout.h index 0ff5dc56..2f136ae0 100644 --- a/dbus/dbus-timeout.h +++ b/dbus/dbus-timeout.h @@ -32,7 +32,7 @@ typedef struct DBusTimeoutList DBusTimeoutList; /* Public methods on DBusTimeout are in dbus-connection.h */ -typedef void (* DBusTimeoutHandler) (void *data); +typedef dbus_bool_t (* DBusTimeoutHandler) (void *data); DBusTimeout* _dbus_timeout_new (int interval, DBusTimeoutHandler handler, diff --git a/dbus/dbus-transport-debug.c b/dbus/dbus-transport-debug.c index a7db3a6e..d477339a 100644 --- a/dbus/dbus-transport-debug.c +++ b/dbus/dbus-transport-debug.c @@ -48,11 +48,13 @@ #define DEFAULT_INTERVAL 1 /** - * Hack due to lack of OOM handling in a couple places + * Hack due to lack of OOM handling in a couple places. + * Need to alloc timeout permanently and enabled/disable so + * that check_timeout won't fail in messages_pending */ #define WAIT_FOR_MEMORY() _dbus_sleep_milliseconds (250) -static void check_timeout (DBusTransport *transport); +static dbus_bool_t check_timeout (DBusTransport *transport); /** * Opaque object representing a debug transport. @@ -123,18 +125,21 @@ move_messages (DBusTransport *transport) return TRUE; } -static void +static dbus_bool_t timeout_handler (void *data) { DBusTransport *transport = data; - while (!move_messages (transport)) - WAIT_FOR_MEMORY (); + if (!move_messages (transport)) + return FALSE; + + if (!check_timeout (transport)) + return FALSE; - check_timeout (transport); + return TRUE; } -static void +static dbus_bool_t check_timeout (DBusTransport *transport) { DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport; @@ -150,9 +155,9 @@ check_timeout (DBusTransport *transport) /* FIXME this can be fixed now, by enabling/disabling * the timeout instead of adding it here */ - while (!_dbus_connection_add_timeout (transport->connection, - debug_transport->timeout)) - WAIT_FOR_MEMORY (); + if (!_dbus_connection_add_timeout (transport->connection, + debug_transport->timeout)) + return FALSE; debug_transport->timeout_added = TRUE; } } @@ -165,6 +170,8 @@ check_timeout (DBusTransport *transport) debug_transport->timeout_added = FALSE; } } + + return TRUE; } static void @@ -189,11 +196,12 @@ debug_finalize (DBusTransport *transport) dbus_free (transport); } -static void +static dbus_bool_t debug_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int flags) { + return TRUE; } static void @@ -204,7 +212,8 @@ debug_disconnect (DBusTransport *transport) static dbus_bool_t debug_connection_set (DBusTransport *transport) { - check_timeout (transport); + if (!check_timeout (transport)) + return FALSE; return TRUE; } @@ -212,7 +221,8 @@ static void debug_messages_pending (DBusTransport *transport, int messages_pending) { - check_timeout (transport); + while (!check_timeout (transport)) + WAIT_FOR_MEMORY (); } static void diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 0f6c45ed..8ee605c0 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -36,36 +36,36 @@ typedef struct DBusTransportVTable DBusTransportVTable; struct DBusTransportVTable { - void (* finalize) (DBusTransport *transport); + void (* finalize) (DBusTransport *transport); /**< The finalize method must free the transport. */ - void (* handle_watch) (DBusTransport *transport, - DBusWatch *watch, - unsigned int flags); + dbus_bool_t (* handle_watch) (DBusTransport *transport, + DBusWatch *watch, + unsigned int flags); /**< The handle_watch method handles reading/writing * data as indicated by the flags. */ - void (* disconnect) (DBusTransport *transport); + void (* disconnect) (DBusTransport *transport); /**< Disconnect this transport. */ - dbus_bool_t (* connection_set) (DBusTransport *transport); + dbus_bool_t (* connection_set) (DBusTransport *transport); /**< Called when transport->connection has been filled in */ - void (* messages_pending) (DBusTransport *transport, - int queue_length); + void (* messages_pending) (DBusTransport *transport, + int queue_length); /**< Called when the outgoing message queue goes from empty * to non-empty or vice versa. */ - void (* do_iteration) (DBusTransport *transport, - unsigned int flags, - int timeout_milliseconds); + void (* do_iteration) (DBusTransport *transport, + unsigned int flags, + int timeout_milliseconds); /**< Called to do a single "iteration" (block on select/poll * followed by reading or writing data). */ - void (* live_messages_changed) (DBusTransport *transport); + void (* live_messages_changed) (DBusTransport *transport); /**< Outstanding messages counter changed */ }; diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index 9ea5ce11..5cbbb1f4 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -61,9 +61,12 @@ struct DBusTransportUnix * outgoing message that have * been written. */ - DBusString encoded_message; /**< Encoded version of current + DBusString encoded_outgoing; /**< Encoded version of current * outgoing message. */ + DBusString encoded_incoming; /**< Encoded version of current + * incoming data. + */ }; static void @@ -99,7 +102,8 @@ unix_finalize (DBusTransport *transport) free_watches (transport); - _dbus_string_free (&unix_transport->encoded_message); + _dbus_string_free (&unix_transport->encoded_outgoing); + _dbus_string_free (&unix_transport->encoded_incoming); _dbus_transport_finalize_base (transport); @@ -180,51 +184,39 @@ do_io_error (DBusTransport *transport) /* return value is whether we successfully read any new data. */ static dbus_bool_t -read_data_into_auth (DBusTransport *transport) +read_data_into_auth (DBusTransport *transport, + dbus_bool_t *oom) { DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; - DBusString buffer; + DBusString *buffer; int bytes_read; - if (!_dbus_string_init (&buffer, _DBUS_INT_MAX)) - { - /* just disconnect if we don't have memory - * to do an authentication - */ - _dbus_verbose ("No memory for authentication\n"); - do_io_error (transport); - return FALSE; - } + *oom = FALSE; + + _dbus_auth_get_buffer (transport->auth, &buffer); bytes_read = _dbus_read (unix_transport->fd, - &buffer, unix_transport->max_bytes_read_per_iteration); + buffer, unix_transport->max_bytes_read_per_iteration); + + _dbus_auth_return_buffer (transport->auth, buffer, + bytes_read > 0 ? bytes_read : 0); if (bytes_read > 0) { _dbus_verbose (" read %d bytes in auth phase\n", bytes_read); - - if (_dbus_auth_bytes_received (transport->auth, - &buffer)) - { - _dbus_string_free (&buffer); - return TRUE; /* We did read some data! woo! */ - } - else - { - /* just disconnect if we don't have memory to do an - * authentication, don't fool with trying to save the buffer - * and who knows what. - */ - _dbus_verbose ("No memory for authentication\n"); - do_io_error (transport); - } + + return TRUE; } else if (bytes_read < 0) { /* EINTR already handled for us */ - - if (errno == EAGAIN || - errno == EWOULDBLOCK) + + if (errno == ENOMEM) + { + *oom = TRUE; + } + else if (errno == EAGAIN || + errno == EWOULDBLOCK) ; /* do nothing, just return FALSE below */ else { @@ -232,15 +224,18 @@ read_data_into_auth (DBusTransport *transport) _dbus_strerror (errno)); do_io_error (transport); } + + return FALSE; } - else if (bytes_read == 0) + else { + _dbus_assert (bytes_read == 0); + _dbus_verbose ("Disconnected from remote app\n"); - do_io_error (transport); + do_io_error (transport); + + return FALSE; } - - _dbus_string_free (&buffer); - return FALSE; } /* Return value is whether we successfully wrote any bytes */ @@ -282,98 +277,6 @@ write_data_from_auth (DBusTransport *transport) return FALSE; } -static void -recover_unused_bytes (DBusTransport *transport) -{ - - if (_dbus_auth_needs_decoding (transport->auth)) - { - DBusString plaintext; - DBusString encoded; - DBusString *buffer; - int orig_len; - - if (!_dbus_string_init (&plaintext, _DBUS_INT_MAX)) - goto nomem; - - if (!_dbus_string_init (&encoded, _DBUS_INT_MAX)) - { - _dbus_string_free (&plaintext); - goto nomem; - } - - if (!_dbus_auth_get_unused_bytes (transport->auth, - &encoded)) - { - _dbus_string_free (&plaintext); - _dbus_string_free (&encoded); - goto nomem; - } - - if (!_dbus_auth_decode_data (transport->auth, - &encoded, &plaintext)) - { - _dbus_string_free (&plaintext); - _dbus_string_free (&encoded); - goto nomem; - } - - _dbus_message_loader_get_buffer (transport->loader, - &buffer); - - orig_len = _dbus_string_get_length (buffer); - - if (!_dbus_string_move (&plaintext, 0, buffer, - orig_len)) - { - _dbus_string_free (&plaintext); - _dbus_string_free (&encoded); - goto nomem; - } - - _dbus_verbose (" %d unused bytes sent to message loader\n", - _dbus_string_get_length (buffer) - - orig_len); - - _dbus_message_loader_return_buffer (transport->loader, - buffer, - _dbus_string_get_length (buffer) - - orig_len); - - _dbus_string_free (&plaintext); - _dbus_string_free (&encoded); - } - else - { - DBusString *buffer; - int orig_len; - - _dbus_message_loader_get_buffer (transport->loader, - &buffer); - - orig_len = _dbus_string_get_length (buffer); - - if (!_dbus_auth_get_unused_bytes (transport->auth, - buffer)) - goto nomem; - - _dbus_verbose (" %d unused bytes sent to message loader\n", - _dbus_string_get_length (buffer) - - orig_len); - - _dbus_message_loader_return_buffer (transport->loader, - buffer, - _dbus_string_get_length (buffer) - - orig_len); - } - - return; - - nomem: - _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); - do_io_error (transport); -} - static void exchange_credentials (DBusTransport *transport, dbus_bool_t do_reading, @@ -418,16 +321,20 @@ exchange_credentials (DBusTransport *transport, } } -static void +static dbus_bool_t do_authentication (DBusTransport *transport, dbus_bool_t do_reading, dbus_bool_t do_writing) -{ +{ + dbus_bool_t oom; + _dbus_transport_ref (transport); + + oom = FALSE; while (!_dbus_transport_get_is_authenticated (transport) && _dbus_transport_get_is_connected (transport)) - { + { exchange_credentials (transport, do_reading, do_writing); if (transport->send_credentials_pending || @@ -443,14 +350,14 @@ do_authentication (DBusTransport *transport, { case DBUS_AUTH_STATE_WAITING_FOR_INPUT: _dbus_verbose (" auth state: waiting for input\n"); - if (!do_reading || !read_data_into_auth (transport)) + if (!do_reading || !read_data_into_auth (transport, &oom)) goto out; break; case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: - /* Screw it, just disconnect */ _dbus_verbose (" auth state: waiting for memory\n"); - do_io_error (transport); + oom = TRUE; + goto out; break; case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND: @@ -466,7 +373,8 @@ do_authentication (DBusTransport *transport, case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES: _dbus_verbose (" auth state: auth with unused bytes\n"); - recover_unused_bytes (transport); + /* We'll recover the unused bytes in dbus-transport.c */ + goto out; break; case DBUS_AUTH_STATE_AUTHENTICATED: @@ -474,26 +382,34 @@ do_authentication (DBusTransport *transport, break; } } - + out: check_read_watch (transport); check_write_watch (transport); _dbus_transport_unref (transport); + + if (oom) + return FALSE; + else + return TRUE; } -static void +/* returns false on oom */ +static dbus_bool_t do_writing (DBusTransport *transport) { int total; DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; - + dbus_bool_t oom; + /* No messages without authentication! */ if (!_dbus_transport_get_is_authenticated (transport)) - return; + return TRUE; if (transport->disconnected) - return; - + return TRUE; + + oom = FALSE; total = 0; while (!transport->disconnected && @@ -513,9 +429,9 @@ do_writing (DBusTransport *transport) goto out; } - if (unix_transport->write_watch == NULL) + if (!dbus_watch_get_enabled (unix_transport->write_watch)) { - _dbus_verbose ("write watch removed, not writing more stuff\n"); + _dbus_verbose ("write watch disabled, not writing more stuff\n"); goto out; } @@ -535,21 +451,25 @@ do_writing (DBusTransport *transport) if (_dbus_auth_needs_encoding (transport->auth)) { - if (_dbus_string_get_length (&unix_transport->encoded_message) == 0) + if (_dbus_string_get_length (&unix_transport->encoded_outgoing) == 0) { if (!_dbus_auth_encode_data (transport->auth, - header, &unix_transport->encoded_message)) - goto out; + header, &unix_transport->encoded_outgoing)) + { + oom = TRUE; + goto out; + } if (!_dbus_auth_encode_data (transport->auth, - body, &unix_transport->encoded_message)) + body, &unix_transport->encoded_outgoing)) { - _dbus_string_set_length (&unix_transport->encoded_message, 0); + _dbus_string_set_length (&unix_transport->encoded_outgoing, 0); + oom = TRUE; goto out; } } - total_bytes_to_write = _dbus_string_get_length (&unix_transport->encoded_message); + total_bytes_to_write = _dbus_string_get_length (&unix_transport->encoded_outgoing); #if 0 _dbus_verbose ("encoded message is %d bytes\n", @@ -558,7 +478,7 @@ do_writing (DBusTransport *transport) bytes_written = _dbus_write (unix_transport->fd, - &unix_transport->encoded_message, + &unix_transport->encoded_outgoing, unix_transport->message_bytes_written, total_bytes_to_write - unix_transport->message_bytes_written); } @@ -621,7 +541,7 @@ do_writing (DBusTransport *transport) if (unix_transport->message_bytes_written == total_bytes_to_write) { unix_transport->message_bytes_written = 0; - _dbus_string_set_length (&unix_transport->encoded_message, 0); + _dbus_string_set_length (&unix_transport->encoded_outgoing, 0); _dbus_connection_message_sent (transport->connection, message); @@ -630,20 +550,27 @@ do_writing (DBusTransport *transport) } out: - return; /* I think some C compilers require a statement after a label */ + if (oom) + return FALSE; + else + return TRUE; } -static void +/* returns false on out-of-memory */ +static dbus_bool_t do_reading (DBusTransport *transport) { DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; DBusString *buffer; int bytes_read; int total; + dbus_bool_t oom; /* No messages without authentication! */ if (!_dbus_transport_get_is_authenticated (transport)) - return; + return TRUE; + + oom = FALSE; total = 0; @@ -651,8 +578,8 @@ do_reading (DBusTransport *transport) /* See if we've exceeded max messages and need to disable reading */ check_read_watch (transport); - if (unix_transport->read_watch == NULL) - return; + if (!dbus_watch_get_enabled (unix_transport->read_watch)) + return TRUE; if (total > unix_transport->max_bytes_read_per_iteration) { @@ -666,15 +593,16 @@ do_reading (DBusTransport *transport) if (_dbus_auth_needs_decoding (transport->auth)) { - DBusString encoded; - - if (!_dbus_string_init (&encoded, _DBUS_INT_MAX)) - goto out; /* not enough memory for the moment */ - - bytes_read = _dbus_read (unix_transport->fd, - &encoded, - unix_transport->max_bytes_read_per_iteration); + if (_dbus_string_get_length (&unix_transport->encoded_incoming) > 0) + bytes_read = _dbus_string_get_length (&unix_transport->encoded_incoming); + else + bytes_read = _dbus_read (unix_transport->fd, + &unix_transport->encoded_incoming, + unix_transport->max_bytes_read_per_iteration); + _dbus_assert (_dbus_string_get_length (&unix_transport->encoded_incoming) == + bytes_read); + if (bytes_read > 0) { int orig_len; @@ -685,24 +613,20 @@ do_reading (DBusTransport *transport) orig_len = _dbus_string_get_length (buffer); if (!_dbus_auth_decode_data (transport->auth, - &encoded, buffer)) + &unix_transport->encoded_incoming, + buffer)) { - /* FIXME argh, we are really fucked here - nowhere to - * put "encoded" while we wait for more memory. Just - * screw it for now and disconnect. The failure may be - * due to badly-encoded data instead of lack of memory - * anyhow. - */ - _dbus_verbose ("Disconnected from remote app due to failure decoding data\n"); - do_io_error (transport); + _dbus_verbose ("Out of memory decoding incoming data\n"); + oom = TRUE; + goto out; } _dbus_message_loader_return_buffer (transport->loader, buffer, _dbus_string_get_length (buffer) - orig_len); - } - _dbus_string_free (&encoded); + _dbus_string_set_length (&unix_transport->encoded_incoming, 0); + } } else { @@ -720,9 +644,15 @@ do_reading (DBusTransport *transport) if (bytes_read < 0) { /* EINTR already handled for us */ - - if (errno == EAGAIN || - errno == EWOULDBLOCK) + + if (errno == ENOMEM) + { + _dbus_verbose ("Out of memory in read()/do_reading()\n"); + oom = TRUE; + goto out; + } + else if (errno == EAGAIN || + errno == EWOULDBLOCK) goto out; else { @@ -745,7 +675,10 @@ do_reading (DBusTransport *transport) total += bytes_read; if (_dbus_transport_queue_messages (transport) == DBUS_DISPATCH_NEED_MEMORY) - goto out; + { + oom = TRUE; + goto out; + } /* Try reading more data until we get EAGAIN and return, or * exceed max bytes per iteration. If in blocking mode of @@ -755,10 +688,13 @@ do_reading (DBusTransport *transport) } out: - return; /* I think some C compilers require a statement after a label */ + if (oom) + return FALSE; + else + return TRUE; } -static void +static dbus_bool_t unix_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int flags) @@ -771,7 +707,7 @@ unix_handle_watch (DBusTransport *transport, if (flags & (DBUS_WATCH_HANGUP | DBUS_WATCH_ERROR)) { _dbus_transport_disconnect (transport); - return; + return TRUE; } if (watch == unix_transport->read_watch && @@ -780,8 +716,11 @@ unix_handle_watch (DBusTransport *transport, #if 0 _dbus_verbose ("handling read watch\n"); #endif - do_authentication (transport, TRUE, FALSE); - do_reading (transport); + if (!do_authentication (transport, TRUE, FALSE)) + return FALSE; + + if (!do_reading (transport)) + return FALSE; } else if (watch == unix_transport->write_watch && (flags & DBUS_WATCH_WRITABLE)) @@ -789,9 +728,14 @@ unix_handle_watch (DBusTransport *transport, #if 0 _dbus_verbose ("handling write watch\n"); #endif - do_authentication (transport, FALSE, TRUE); - do_writing (transport); + if (!do_authentication (transport, FALSE, TRUE)) + return FALSE; + + if (!do_writing (transport)) + return FALSE; } + + return TRUE; } static void @@ -1031,26 +975,30 @@ _dbus_transport_new_for_fd (int fd, if (unix_transport == NULL) return NULL; - if (!_dbus_string_init (&unix_transport->encoded_message, + if (!_dbus_string_init (&unix_transport->encoded_outgoing, _DBUS_INT_MAX)) goto failed_0; + if (!_dbus_string_init (&unix_transport->encoded_incoming, + _DBUS_INT_MAX)) + goto failed_1; + unix_transport->write_watch = _dbus_watch_new (fd, DBUS_WATCH_WRITABLE, FALSE); if (unix_transport->write_watch == NULL) - goto failed_1; + goto failed_2; unix_transport->read_watch = _dbus_watch_new (fd, DBUS_WATCH_READABLE, FALSE); if (unix_transport->read_watch == NULL) - goto failed_2; + goto failed_3; if (!_dbus_transport_init_base (&unix_transport->base, &unix_vtable, server)) - goto failed_3; + goto failed_4; unix_transport->fd = fd; unix_transport->message_bytes_written = 0; @@ -1061,12 +1009,14 @@ _dbus_transport_new_for_fd (int fd, return (DBusTransport*) unix_transport; - failed_3: + failed_4: _dbus_watch_unref (unix_transport->read_watch); - failed_2: + failed_3: _dbus_watch_unref (unix_transport->write_watch); + failed_2: + _dbus_string_free (&unix_transport->encoded_incoming); failed_1: - _dbus_string_free (&unix_transport->encoded_message); + _dbus_string_free (&unix_transport->encoded_outgoing); failed_0: dbus_free (unix_transport); return NULL; diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index b2355ea5..8087f5b0 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -265,6 +265,8 @@ _dbus_transport_open (const char *address, void _dbus_transport_ref (DBusTransport *transport) { + _dbus_assert (transport->refcount > 0); + transport->refcount += 1; } @@ -306,14 +308,12 @@ _dbus_transport_disconnect (DBusTransport *transport) if (transport->disconnected) return; - _dbus_transport_ref (transport); (* transport->vtable->disconnect) (transport); transport->disconnected = TRUE; - _dbus_connection_notify_disconnected (transport->connection); - - _dbus_transport_unref (transport); + if (transport->connection) + _dbus_connection_notify_disconnected (transport->connection); } /** @@ -394,30 +394,35 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) * @param transport the transport. * @param watch the watch. * @param condition the current state of the watched file descriptor. + * @returns #FALSE if not enough memory to fully handle the watch */ -void +dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int condition) { + dbus_bool_t retval; + _dbus_assert (transport->vtable->handle_watch != NULL); if (transport->disconnected) - return; + return TRUE; if (dbus_watch_get_fd (watch) < 0) { _dbus_warn ("Tried to handle an invalidated watch; this watch should have been removed\n"); - return; + return TRUE; } _dbus_watch_sanitize_condition (watch, &condition); _dbus_transport_ref (transport); _dbus_watch_ref (watch); - (* transport->vtable->handle_watch) (transport, watch, condition); + retval = (* transport->vtable->handle_watch) (transport, watch, condition); _dbus_watch_unref (watch); _dbus_transport_unref (transport); + + return retval; } /** @@ -506,6 +511,98 @@ _dbus_transport_do_iteration (DBusTransport *transport, _dbus_transport_unref (transport); } +static dbus_bool_t +recover_unused_bytes (DBusTransport *transport) +{ + if (_dbus_auth_do_work (transport->auth) != DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES) + return TRUE; + + if (_dbus_auth_needs_decoding (transport->auth)) + { + DBusString plaintext; + const DBusString *encoded; + DBusString *buffer; + int orig_len; + + if (!_dbus_string_init (&plaintext, _DBUS_INT_MAX)) + goto nomem; + + _dbus_auth_get_unused_bytes (transport->auth, + &encoded); + + if (!_dbus_auth_decode_data (transport->auth, + encoded, &plaintext)) + { + _dbus_string_free (&plaintext); + goto nomem; + } + + _dbus_message_loader_get_buffer (transport->loader, + &buffer); + + orig_len = _dbus_string_get_length (buffer); + + if (!_dbus_string_move (&plaintext, 0, buffer, + orig_len)) + { + _dbus_string_free (&plaintext); + goto nomem; + } + + _dbus_verbose (" %d unused bytes sent to message loader\n", + _dbus_string_get_length (buffer) - + orig_len); + + _dbus_message_loader_return_buffer (transport->loader, + buffer, + _dbus_string_get_length (buffer) - + orig_len); + + _dbus_auth_delete_unused_bytes (transport->auth); + + _dbus_string_free (&plaintext); + } + else + { + const DBusString *bytes; + DBusString *buffer; + int orig_len; + dbus_bool_t succeeded; + + _dbus_message_loader_get_buffer (transport->loader, + &buffer); + + orig_len = _dbus_string_get_length (buffer); + + _dbus_auth_get_unused_bytes (transport->auth, + &bytes); + + succeeded = TRUE; + if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) + succeeded = FALSE; + + _dbus_verbose (" %d unused bytes sent to message loader\n", + _dbus_string_get_length (buffer) - + orig_len); + + _dbus_message_loader_return_buffer (transport->loader, + buffer, + _dbus_string_get_length (buffer) - + orig_len); + + if (succeeded) + _dbus_auth_delete_unused_bytes (transport->auth); + else + goto nomem; + } + + return TRUE; + + nomem: + _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); + return FALSE; +} + /** * Reports our current dispatch status (whether there's buffered * data to be queued as messages, or not, or we need memory). @@ -519,6 +616,21 @@ _dbus_transport_get_dispatch_status (DBusTransport *transport) if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size) return DBUS_DISPATCH_COMPLETE; /* complete for now */ + if (!_dbus_transport_get_is_authenticated (transport)) + { + switch (_dbus_auth_do_work (transport->auth)) + { + case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: + return DBUS_DISPATCH_NEED_MEMORY; + case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES: + if (!recover_unused_bytes (transport)) + return DBUS_DISPATCH_NEED_MEMORY; + break; + default: + break; + } + } + if (!_dbus_message_loader_queue_messages (transport->loader)) return DBUS_DISPATCH_NEED_MEMORY; diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index ad3299c2..639a7d50 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -37,7 +37,7 @@ void _dbus_transport_unref (DBusTransport *t void _dbus_transport_disconnect (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_connected (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport); -void _dbus_transport_handle_watch (DBusTransport *transport, +dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int condition); dbus_bool_t _dbus_transport_set_connection (DBusTransport *transport, diff --git a/dbus/dbus-watch.c b/dbus/dbus-watch.c index 1fdbc7ac..c4f1af4a 100644 --- a/dbus/dbus-watch.c +++ b/dbus/dbus-watch.c @@ -63,6 +63,9 @@ _dbus_watch_new (int fd, _dbus_assert ((flags & VALID_WATCH_FLAGS) == flags); watch = dbus_new0 (DBusWatch, 1); + if (watch == NULL) + return NULL; + watch->refcount = 1; watch->fd = fd; watch->flags = flags; -- cgit