diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2021-02-25 11:45:33 +0100 |
---|---|---|
committer | Carlos Garcia Campos <cgarcia@igalia.com> | 2021-02-25 15:57:51 +0100 |
commit | 69dc2314e881487cbf8147f6c48b9e8d2e258358 (patch) | |
tree | 55e16bf48b3428c3fa52f798b1f16741bd865c18 | |
parent | b45a7f2e0f80af10915be982f28c4888b18fd954 (diff) | |
download | libsoup-69dc2314e881487cbf8147f6c48b9e8d2e258358.tar.gz |
session: remove async-context property
Stop supporting multiple contexts, the session is expected to be used
always in the thread from which it was created.
-rw-r--r-- | libsoup/auth/soup-auth-manager.c | 33 | ||||
-rw-r--r-- | libsoup/server/soup-server-io.c | 14 | ||||
-rw-r--r-- | libsoup/soup-logger.c | 23 | ||||
-rw-r--r-- | libsoup/soup-message-io-data.c | 2 | ||||
-rw-r--r-- | libsoup/soup-message-io-data.h | 1 | ||||
-rw-r--r-- | libsoup/soup-message-io.c | 9 | ||||
-rw-r--r-- | libsoup/soup-message-queue.c | 31 | ||||
-rw-r--r-- | libsoup/soup-message-queue.h | 2 | ||||
-rw-r--r-- | libsoup/soup-session.c | 175 | ||||
-rw-r--r-- | libsoup/websocket/soup-websocket-connection.c | 13 | ||||
-rw-r--r-- | tests/context-test.c | 139 |
11 files changed, 102 insertions, 340 deletions
diff --git a/libsoup/auth/soup-auth-manager.c b/libsoup/auth/soup-auth-manager.c index 4561936c..2ab924f3 100644 --- a/libsoup/auth/soup-auth-manager.c +++ b/libsoup/auth/soup-auth-manager.c @@ -73,7 +73,6 @@ typedef struct { GPtrArray *auth_types; gboolean auto_ntlm; - GMutex lock; SoupAuth *proxy_auth; GHashTable *auth_hosts; } SoupAuthManagerPrivate; @@ -104,7 +103,6 @@ soup_auth_manager_init (SoupAuthManager *manager) soup_uri_host_equal, NULL, (GDestroyNotify)soup_auth_host_free); - g_mutex_init (&priv->lock); } static void @@ -118,8 +116,6 @@ soup_auth_manager_finalize (GObject *object) g_clear_object (&priv->proxy_auth); - g_mutex_clear (&priv->lock); - G_OBJECT_CLASS (soup_auth_manager_parent_class)->finalize (object); } @@ -638,8 +634,6 @@ auth_got_headers (SoupMessage *msg, gpointer manager) SoupAuth *auth, *prior_auth; gboolean prior_auth_failed = FALSE; - g_mutex_lock (&priv->lock); - /* See if we used auth last time */ prior_auth = soup_message_get_auth (msg); if (prior_auth && check_auth (msg, prior_auth)) { @@ -648,10 +642,8 @@ auth_got_headers (SoupMessage *msg, gpointer manager) prior_auth_failed = TRUE; } else { auth = create_auth (priv, msg); - if (!auth) { - g_mutex_unlock (&priv->lock); + if (!auth) return; - } } if (!soup_message_query_flags (msg, SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) { @@ -668,7 +660,6 @@ auth_got_headers (SoupMessage *msg, gpointer manager) prior_auth_failed, FALSE, TRUE); soup_message_set_auth (msg, auth); g_object_unref (auth); - g_mutex_unlock (&priv->lock); } static void @@ -677,7 +668,6 @@ auth_got_body (SoupMessage *msg, gpointer manager) SoupAuthManagerPrivate *priv = soup_auth_manager_get_instance_private (manager); SoupAuth *auth; - g_mutex_lock (&priv->lock); auth = lookup_auth (priv, msg); if (auth && soup_auth_is_ready (auth, msg)) { if (SOUP_IS_CONNECTION_AUTH (auth)) @@ -691,7 +681,6 @@ auth_got_body (SoupMessage *msg, gpointer manager) soup_session_requeue_message (priv->session, msg); } - g_mutex_unlock (&priv->lock); } static void @@ -701,8 +690,6 @@ proxy_auth_got_headers (SoupMessage *msg, gpointer manager) SoupAuth *auth = NULL, *prior_auth; gboolean prior_auth_failed = FALSE; - g_mutex_lock (&priv->lock); - /* See if we used auth last time */ prior_auth = soup_message_get_proxy_auth (msg); if (prior_auth && check_auth (msg, prior_auth)) { @@ -715,10 +702,9 @@ proxy_auth_got_headers (SoupMessage *msg, gpointer manager) if (!auth) { auth = create_auth (priv, msg); - if (!auth) { - g_mutex_unlock (&priv->lock); + if (!auth) return; - } + if (!soup_message_query_flags (msg, SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) priv->proxy_auth = g_object_ref (auth); } @@ -728,7 +714,6 @@ proxy_auth_got_headers (SoupMessage *msg, gpointer manager) prior_auth_failed, TRUE, TRUE); soup_message_set_proxy_auth (msg, auth); g_object_unref (auth); - g_mutex_unlock (&priv->lock); } static void @@ -737,8 +722,6 @@ proxy_auth_got_body (SoupMessage *msg, gpointer manager) SoupAuthManagerPrivate *priv = soup_auth_manager_get_instance_private (manager); SoupAuth *auth; - g_mutex_lock (&priv->lock); - auth = lookup_proxy_auth (priv, msg); if (auth && soup_auth_is_ready (auth, msg)) { /* When not using cached credentials, update the Authorization header @@ -748,8 +731,6 @@ proxy_auth_got_body (SoupMessage *msg, gpointer manager) update_authorization_header (msg, auth, TRUE); soup_session_requeue_message (priv->session, msg); } - - g_mutex_unlock (&priv->lock); } static void @@ -761,8 +742,6 @@ auth_msg_starting (SoupMessage *msg, gpointer manager) if (soup_message_query_flags (msg, SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) return; - g_mutex_lock (&priv->lock); - if (soup_message_get_method (msg) != SOUP_METHOD_CONNECT) { auth = lookup_auth (priv, msg); if (auth) { @@ -782,8 +761,6 @@ auth_msg_starting (SoupMessage *msg, gpointer manager) } soup_message_set_proxy_auth (msg, auth); update_authorization_header (msg, auth, TRUE); - - g_mutex_unlock (&priv->lock); } static void @@ -840,9 +817,7 @@ soup_auth_manager_use_auth (SoupAuthManager *manager, { SoupAuthManagerPrivate *priv = soup_auth_manager_get_instance_private (manager); - g_mutex_lock (&priv->lock); record_auth_for_uri (priv, uri, auth, FALSE); - g_mutex_unlock (&priv->lock); } /** @@ -859,9 +834,7 @@ soup_auth_manager_clear_cached_credentials (SoupAuthManager *manager) g_return_if_fail (SOUP_IS_AUTH_MANAGER (manager)); - g_mutex_lock (&priv->lock); g_hash_table_remove_all (priv->auth_hosts); - g_mutex_unlock (&priv->lock); } static void diff --git a/libsoup/server/soup-server-io.c b/libsoup/server/soup-server-io.c index 7d2831cd..9359293a 100644 --- a/libsoup/server/soup-server-io.c +++ b/libsoup/server/soup-server-io.c @@ -26,6 +26,8 @@ struct _SoupServerMessageIOData { goffset write_body_offset; GSource *unpause_source; + + GMainContext *async_context; }; #define RESPONSE_BLOCK_SIZE 8192 @@ -45,6 +47,7 @@ soup_server_message_io_data_free (SoupServerMessageIOData *io) io->unpause_source = NULL; } + g_clear_pointer (&io->async_context, g_main_context_unref); g_clear_pointer (&io->write_chunk, g_bytes_unref); g_slice_free (SoupServerMessageIOData, io); @@ -488,11 +491,11 @@ io_write (SoupServerMessage *msg, g_clear_object (&io->body_ostream); } else { io->async_wait = g_cancellable_new (); - g_main_context_push_thread_default (io->async_context); + g_main_context_push_thread_default (server_io->async_context); g_output_stream_close_async (io->body_ostream, G_PRIORITY_DEFAULT, NULL, closed_async, g_object_ref (msg)); - g_main_context_pop_thread_default (io->async_context); + g_main_context_pop_thread_default (server_io->async_context); } } @@ -850,7 +853,7 @@ io_run (SoupServerMessage *msg) io->io_source = soup_message_io_data_get_source (io, G_OBJECT (msg), NULL, (SoupMessageIOSourceFunc)io_run_ready, NULL); - g_source_attach (io->io_source, io->async_context); + g_source_attach (io->io_source, server_io->async_context); } else if (soup_server_message_get_io_data (msg) == server_io) { soup_server_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, error ? error->message : NULL); soup_server_message_io_finished (msg); @@ -875,7 +878,6 @@ soup_server_message_read_request (SoupServerMessage *msg, io->base.iostream = g_object_ref (soup_socket_get_iostream (sock)); io->base.istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (io->base.iostream)); io->base.ostream = g_io_stream_get_output_stream (io->base.iostream); - io->base.async_context = g_main_context_ref_thread_default (); io->base.read_header_buf = g_byte_array_new (); io->base.write_buf = g_string_new (NULL); @@ -883,6 +885,8 @@ soup_server_message_read_request (SoupServerMessage *msg, io->base.read_state = SOUP_MESSAGE_IO_STATE_HEADERS; io->base.write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED; + io->async_context = g_main_context_ref_thread_default (); + soup_server_message_set_io_data (msg, io); io_run (msg); @@ -928,7 +932,7 @@ soup_server_message_io_unpause (SoupServerMessage *msg) g_return_if_fail (io != NULL); if (!io->unpause_source) { - io->unpause_source = soup_add_completion_reffed (io->base.async_context, + io->unpause_source = soup_add_completion_reffed (io->async_context, io_unpause_internal, msg, NULL); } } diff --git a/libsoup/soup-logger.c b/libsoup/soup-logger.c index 29a089a1..72afb012 100644 --- a/libsoup/soup-logger.c +++ b/libsoup/soup-logger.c @@ -97,11 +97,6 @@ struct _SoupLogger { }; typedef struct { - /* We use a mutex so that if requests are being run in - * multiple threads, we don't mix up the output. - */ - GMutex lock; - GQuark tag; GHashTable *ids; @@ -142,7 +137,6 @@ soup_logger_init (SoupLogger *logger) SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); char *id; - g_mutex_init (&priv->lock); id = g_strdup_printf ("SoupLogger-%p", logger); priv->tag = g_quark_from_string (id); g_free (id); @@ -164,8 +158,6 @@ soup_logger_finalize (GObject *object) if (priv->printer_dnotify) priv->printer_dnotify (priv->printer_data); - g_mutex_clear (&priv->lock); - G_OBJECT_CLASS (soup_logger_parent_class)->finalize (object); } @@ -572,23 +564,15 @@ static void finished (SoupMessage *msg, gpointer user_data) { SoupLogger *logger = user_data; - SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); - - g_mutex_lock (&priv->lock); print_response (logger, msg); soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); - - g_mutex_unlock (&priv->lock); } static void got_informational (SoupMessage *msg, gpointer user_data) { SoupLogger *logger = user_data; - SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); - - g_mutex_lock (&priv->lock); g_signal_handlers_disconnect_by_func (msg, finished, logger); print_response (logger, msg); @@ -599,23 +583,16 @@ got_informational (SoupMessage *msg, gpointer user_data) "[Now sending request body...]"); soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); } - - g_mutex_unlock (&priv->lock); } static void got_body (SoupMessage *msg, gpointer user_data) { SoupLogger *logger = user_data; - SoupLoggerPrivate *priv = soup_logger_get_instance_private (logger); - - g_mutex_lock (&priv->lock); g_signal_handlers_disconnect_by_func (msg, finished, logger); print_response (logger, msg); soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', "\n"); - - g_mutex_unlock (&priv->lock); } static void diff --git a/libsoup/soup-message-io-data.c b/libsoup/soup-message-io-data.c index 9fd76e5b..e9b16e9f 100644 --- a/libsoup/soup-message-io-data.c +++ b/libsoup/soup-message-io-data.c @@ -34,8 +34,6 @@ soup_message_io_data_cleanup (SoupMessageIOData *io) g_object_unref (io->body_istream); if (io->body_ostream) g_object_unref (io->body_ostream); - if (io->async_context) - g_main_context_unref (io->async_context); g_byte_array_free (io->read_header_buf, TRUE); diff --git a/libsoup/soup-message-io-data.h b/libsoup/soup-message-io-data.h index 0476a425..0e3eb77b 100644 --- a/libsoup/soup-message-io-data.h +++ b/libsoup/soup-message-io-data.h @@ -47,7 +47,6 @@ typedef struct { GInputStream *body_istream; GOutputStream *ostream; GOutputStream *body_ostream; - GMainContext *async_context; SoupMessageIOState read_state; SoupEncoding read_encoding; diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 1957bc9b..6503892c 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -392,7 +392,6 @@ io_write (SoupMessage *msg, gboolean blocking, break; } else { io->async_wait = g_cancellable_new (); - g_main_context_push_thread_default (io->async_context); g_output_stream_splice_async (io->body_ostream, soup_message_get_request_body_stream (msg), G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, @@ -400,7 +399,6 @@ io_write (SoupMessage *msg, gboolean blocking, cancellable, (GAsyncReadyCallback)request_body_stream_wrote_cb, g_object_ref (msg)); - g_main_context_pop_thread_default (io->async_context); return FALSE; } } else @@ -415,12 +413,10 @@ io_write (SoupMessage *msg, gboolean blocking, g_clear_object (&io->body_ostream); } else { io->async_wait = g_cancellable_new (); - g_main_context_push_thread_default (io->async_context); g_output_stream_close_async (io->body_ostream, soup_client_message_io_data_get_priority (client_io), cancellable, closed_async, g_object_ref (msg)); - g_main_context_pop_thread_default (io->async_context); } } @@ -809,7 +805,7 @@ soup_message_io_run (SoupMessage *msg, NULL); g_source_set_priority (io->io_source, soup_client_message_io_data_get_priority (client_io)); - g_source_attach (io->io_source, io->async_context); + g_source_attach (io->io_source, g_main_context_get_thread_default ()); } else { if (soup_message_get_io_data (msg) == client_io) soup_message_io_finish (msg, error); @@ -882,7 +878,7 @@ io_run_until_read_async (SoupMessage *msg, (SoupMessageIOSourceFunc)io_run_until_read_ready, task); g_source_set_priority (io->io_source, g_task_get_priority (task)); - g_source_attach (io->io_source, io->async_context); + g_source_attach (io->io_source, g_main_context_get_thread_default ()); return; } @@ -980,7 +976,6 @@ soup_message_send_request (SoupMessageQueueItem *item, io->base.iostream = g_object_ref (soup_connection_get_iostream (io->item->conn)); io->base.istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (io->base.iostream)); io->base.ostream = g_io_stream_get_output_stream (io->base.iostream); - io->base.async_context = g_main_context_ref_thread_default (); io->base.read_header_buf = g_byte_array_new (); io->base.write_buf = g_string_new (NULL); diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index f1422b19..5e04d306 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -29,7 +29,6 @@ struct _SoupMessageQueue { SoupSession *session; - GMutex mutex; SoupMessageQueueItem *head, *tail; }; @@ -40,7 +39,7 @@ soup_message_queue_new (SoupSession *session) queue = g_slice_new0 (SoupMessageQueue); queue->session = session; - g_mutex_init (&queue->mutex); + return queue; } @@ -49,7 +48,6 @@ soup_message_queue_destroy (SoupMessageQueue *queue) { g_return_if_fail (queue->head == NULL); - g_mutex_clear (&queue->mutex); g_slice_free (SoupMessageQueue, queue); } @@ -84,9 +82,6 @@ soup_message_queue_append (SoupMessageQueue *queue, item = g_slice_new0 (SoupMessageQueueItem); item->session = g_object_ref (queue->session); - item->async_context = g_main_context_get_thread_default (); - if (item->async_context) - g_main_context_ref (item->async_context); item->queue = queue; item->msg = g_object_ref (msg); item->callback = callback; @@ -103,7 +98,6 @@ soup_message_queue_append (SoupMessageQueue *queue, */ item->ref_count = 1; - g_mutex_lock (&queue->mutex); if (queue->head) { SoupMessageQueueItem *it = queue->head; @@ -129,7 +123,6 @@ soup_message_queue_append (SoupMessageQueue *queue, } else queue->head = queue->tail = item; - g_mutex_unlock (&queue->mutex); return item; } @@ -142,9 +135,7 @@ soup_message_queue_append (SoupMessageQueue *queue, void soup_message_queue_item_ref (SoupMessageQueueItem *item) { - g_mutex_lock (&item->queue->mutex); item->ref_count++; - g_mutex_unlock (&item->queue->mutex); } /** @@ -158,15 +149,11 @@ soup_message_queue_item_ref (SoupMessageQueueItem *item) void soup_message_queue_item_unref (SoupMessageQueueItem *item) { - g_mutex_lock (&item->queue->mutex); - /* Decrement the ref_count; if it's still non-zero OR if the * item is still in the queue, then return. */ - if (--item->ref_count || !item->removed) { - g_mutex_unlock (&item->queue->mutex); + if (--item->ref_count || !item->removed) return; - } g_warn_if_fail (item->conn == NULL); @@ -180,8 +167,6 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) else item->queue->tail = item->prev; - g_mutex_unlock (&item->queue->mutex); - /* And free it */ g_signal_handlers_disconnect_by_func (item->msg, queue_message_restarted, item); @@ -190,7 +175,6 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) g_object_unref (item->cancellable); g_clear_error (&item->error); g_clear_object (&item->task); - g_clear_pointer (&item->async_context, g_main_context_unref); g_slice_free (SoupMessageQueueItem, item); } @@ -210,8 +194,6 @@ soup_message_queue_lookup (SoupMessageQueue *queue, SoupMessage *msg) { SoupMessageQueueItem *item; - g_mutex_lock (&queue->mutex); - item = queue->tail; while (item && (item->removed || item->msg != msg)) item = item->prev; @@ -219,7 +201,6 @@ soup_message_queue_lookup (SoupMessageQueue *queue, SoupMessage *msg) if (item) item->ref_count++; - g_mutex_unlock (&queue->mutex); return item; } @@ -240,8 +221,6 @@ soup_message_queue_first (SoupMessageQueue *queue) { SoupMessageQueueItem *item; - g_mutex_lock (&queue->mutex); - item = queue->head; while (item && item->removed) item = item->next; @@ -249,7 +228,6 @@ soup_message_queue_first (SoupMessageQueue *queue) if (item) item->ref_count++; - g_mutex_unlock (&queue->mutex); return item; } @@ -270,15 +248,12 @@ soup_message_queue_next (SoupMessageQueue *queue, SoupMessageQueueItem *item) { SoupMessageQueueItem *next; - g_mutex_lock (&queue->mutex); - next = item->next; while (next && next->removed) next = next->next; if (next) next->ref_count++; - g_mutex_unlock (&queue->mutex); soup_message_queue_item_unref (item); return next; } @@ -296,7 +271,5 @@ soup_message_queue_remove (SoupMessageQueue *queue, SoupMessageQueueItem *item) { g_return_if_fail (!item->removed); - g_mutex_lock (&queue->mutex); item->removed = TRUE; - g_mutex_unlock (&queue->mutex); } diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index e030adaf..c9cab022 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -39,7 +39,6 @@ struct _SoupMessageQueueItem { SoupMessage *msg; SoupSessionCallback callback; gpointer callback_data; - GMainContext *async_context; GCancellable *cancellable; GError *error; @@ -50,7 +49,6 @@ struct _SoupMessageQueueItem { guint paused : 1; guint io_started : 1; guint async : 1; - guint async_pending : 1; guint connect_only : 1; guint priority : 3; guint resend_count : 5; diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 663d8345..77c1f81c 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -106,6 +106,7 @@ typedef struct { SoupSocketProperties *socket_props; SoupMessageQueue *queue; + GSource *queue_source; char *user_agent; char *accept_language; @@ -118,19 +119,6 @@ typedef struct { GHashTable *conns; /* SoupConnection -> SoupSessionHost */ guint num_conns; guint max_conns, max_conns_per_host; - - /* Must hold the conn_lock before potentially creating a new - * SoupSessionHost, adding/removing a connection, - * disconnecting a connection, moving a connection from - * IDLE to IN_USE, or when updating socket properties. - * Must not emit signals or destroy objects while holding it. - * The conn_cond is signaled when it may be possible for - * a previously-blocked message to continue. - */ - GMutex conn_lock; - GCond conn_cond; - - GMainContext *async_context; } SoupSessionPrivate; static void free_host (SoupSessionHost *host); @@ -176,7 +164,6 @@ enum { PROP_MAX_CONNS, PROP_MAX_CONNS_PER_HOST, PROP_TLS_DATABASE, - PROP_ASYNC_CONTEXT, PROP_TIMEOUT, PROP_USER_AGENT, PROP_ACCEPT_LANGUAGE, @@ -216,18 +203,46 @@ enum { */ G_DEFINE_QUARK (soup-session-error-quark, soup_session_error) +typedef struct { + GSource source; + SoupSession* session; +} SoupMessageQueueSource; + +static gboolean +queue_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + SoupSession *session = ((SoupMessageQueueSource *)source)->session; + + g_source_set_ready_time (source, -1); + async_run_queue (session); + return G_SOURCE_CONTINUE; +} + +static GSourceFuncs queue_source_funcs = { + NULL, //queue_prepare, + NULL, //queue_check, + queue_dispatch, + NULL, NULL, NULL +}; + static void soup_session_init (SoupSession *session) { SoupSessionPrivate *priv = soup_session_get_instance_private (session); SoupAuthManager *auth_manager; + SoupMessageQueueSource *source; priv->queue = soup_message_queue_new (session); - priv->async_context = g_main_context_ref_thread_default (); + priv->queue_source = g_source_new (&queue_source_funcs, sizeof (SoupMessageQueueSource)); + source = (SoupMessageQueueSource *)priv->queue_source; + source->session = session; + g_source_set_name (priv->queue_source, "SoupMessageQueue"); + g_source_set_can_recurse (priv->queue_source, TRUE); + g_source_attach (priv->queue_source, g_main_context_get_thread_default ()); priv->io_timeout = priv->idle_timeout = 60; - g_mutex_init (&priv->conn_lock); - g_cond_init (&priv->conn_cond); priv->http_hosts = g_hash_table_new_full (soup_host_uri_hash, soup_host_uri_equal, NULL, (GDestroyNotify)free_host); @@ -272,6 +287,8 @@ soup_session_dispose (GObject *object) while (priv->features) soup_session_remove_feature (session, priv->features->data); + g_source_destroy (priv->queue_source); + G_OBJECT_CLASS (soup_session_parent_class)->dispose (object); } @@ -282,9 +299,8 @@ soup_session_finalize (GObject *object) SoupSessionPrivate *priv = soup_session_get_instance_private (session); soup_message_queue_destroy (priv->queue); + g_source_unref (priv->queue_source); - g_mutex_clear (&priv->conn_lock); - g_cond_clear (&priv->conn_cond); g_hash_table_destroy (priv->http_hosts); g_hash_table_destroy (priv->https_hosts); g_hash_table_destroy (priv->conns); @@ -295,7 +311,6 @@ soup_session_finalize (GObject *object) g_clear_object (&priv->tlsdb); g_clear_object (&priv->tls_interaction); - g_clear_pointer (&priv->async_context, g_main_context_unref); g_clear_object (&priv->local_addr); g_hash_table_destroy (priv->features_cache); @@ -307,7 +322,6 @@ soup_session_finalize (GObject *object) G_OBJECT_CLASS (soup_session_parent_class)->finalize (object); } -/* requires conn_lock */ static void ensure_socket_props (SoupSession *session) { @@ -331,13 +345,12 @@ socket_props_changed (SoupSession *session) { SoupSessionPrivate *priv = soup_session_get_instance_private (session); - g_mutex_lock (&priv->conn_lock); - if (priv->socket_props) { - soup_socket_properties_unref (priv->socket_props); - priv->socket_props = NULL; - ensure_socket_props (session); - } - g_mutex_unlock (&priv->conn_lock); + if (!priv->socket_props) + return; + + soup_socket_properties_unref (priv->socket_props); + priv->socket_props = NULL; + ensure_socket_props (session); } static void @@ -996,7 +1009,6 @@ soup_session_host_new (SoupSession *session, GUri *uri) return host; } -/* Requires conn_lock to be locked */ static SoupSessionHost * get_host_for_uri (SoupSession *session, GUri *uri) { @@ -1030,7 +1042,6 @@ get_host_for_uri (SoupSession *session, GUri *uri) return host; } -/* Requires conn_lock to be locked */ static SoupSessionHost * get_host_for_message (SoupSession *session, SoupMessage *msg) { @@ -1266,10 +1277,8 @@ soup_session_append_queue_item (SoupSession *session, item = soup_message_queue_append (priv->queue, msg, cancellable, callback, user_data); item->async = async; - g_mutex_lock (&priv->conn_lock); host = get_host_for_message (session, item->msg); host->num_messages++; - g_mutex_unlock (&priv->conn_lock); if (!soup_message_query_flags (msg, SOUP_MESSAGE_NO_REDIRECT)) { soup_message_add_header_handler ( @@ -1362,7 +1371,6 @@ soup_session_cleanup_connections (SoupSession *session, gpointer conn, host; SoupConnectionState state; - g_mutex_lock (&priv->conn_lock); g_hash_table_iter_init (&iter, priv->conns); while (g_hash_table_iter_next (&iter, &conn, &host)) { state = soup_connection_get_state (conn); @@ -1373,7 +1381,6 @@ soup_session_cleanup_connections (SoupSession *session, drop_connection (session, host, conn); } } - g_mutex_unlock (&priv->conn_lock); if (!conns) return FALSE; @@ -1395,15 +1402,8 @@ free_unused_host (gpointer user_data) SoupSessionPrivate *priv = soup_session_get_instance_private (host->session); GUri *uri = host->uri; - g_mutex_lock (&priv->conn_lock); - - /* In a multithreaded session, a connection might have been - * added while we were waiting for conn_lock. - */ - if (host->connections) { - g_mutex_unlock (&priv->conn_lock); + if (host->connections) return FALSE; - } /* This will free the host in addition to removing it from the * hash table @@ -1412,7 +1412,6 @@ free_unused_host (gpointer user_data) g_hash_table_remove (priv->https_hosts, uri); else g_hash_table_remove (priv->http_hosts, uri); - g_mutex_unlock (&priv->conn_lock); return FALSE; } @@ -1422,10 +1421,6 @@ drop_connection (SoupSession *session, SoupSessionHost *host, SoupConnection *co { SoupSessionPrivate *priv = soup_session_get_instance_private (session); - /* Note: caller must hold conn_lock, and must remove @conn - * from priv->conns itself. - */ - if (host) { host->connections = g_slist_remove (host->connections, conn); host->num_conns--; @@ -1436,7 +1431,7 @@ drop_connection (SoupSession *session, SoupSessionHost *host, SoupConnection *co */ if (host->num_conns == 0) { g_assert (host->keep_alive_src == NULL); - host->keep_alive_src = soup_add_timeout (priv->async_context, + host->keep_alive_src = soup_add_timeout (g_main_context_get_thread_default (), HOST_KEEP_ALIVE, free_unused_host, host); @@ -1457,15 +1452,11 @@ connection_disconnected (SoupConnection *conn, gpointer user_data) SoupSessionPrivate *priv = soup_session_get_instance_private (session); SoupSessionHost *host; - g_mutex_lock (&priv->conn_lock); - host = g_hash_table_lookup (priv->conns, conn); if (host) g_hash_table_remove (priv->conns, conn); drop_connection (session, host, conn); - g_mutex_unlock (&priv->conn_lock); - soup_session_kick_queue (session); } @@ -1501,11 +1492,8 @@ soup_session_unqueue_item (SoupSession *session, soup_message_queue_remove (priv->queue, item); - g_mutex_lock (&priv->conn_lock); host = get_host_for_message (session, item->msg); host->num_messages--; - g_cond_broadcast (&priv->conn_cond); - g_mutex_unlock (&priv->conn_lock); /* g_signal_handlers_disconnect_by_func doesn't work if you * have a metamarshal, meaning it doesn't work with @@ -1699,7 +1687,6 @@ connect_async_complete (GObject *object, soup_message_queue_item_unref (item); } -/* requires conn_lock */ static SoupConnection * get_connection_for_host (SoupSession *session, SoupMessageQueueItem *item, @@ -1780,7 +1767,6 @@ static gboolean get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) { SoupSession *session = item->session; - SoupSessionPrivate *priv = soup_session_get_instance_private (session); SoupSessionHost *host; SoupConnection *conn = NULL; gboolean my_should_cleanup = FALSE; @@ -1793,7 +1779,6 @@ get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) (!soup_message_query_flags (item->msg, SOUP_MESSAGE_IDEMPOTENT) && !SOUP_METHOD_IS_IDEMPOTENT (soup_message_get_method (item->msg))); - g_mutex_lock (&priv->conn_lock); host = get_host_for_message (session, item->msg); while (TRUE) { conn = get_connection_for_host (session, item, host, @@ -1803,17 +1788,11 @@ get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) break; if (my_should_cleanup) { - g_mutex_unlock (&priv->conn_lock); soup_session_cleanup_connections (session, TRUE); - g_mutex_lock (&priv->conn_lock); - my_should_cleanup = FALSE; continue; } - - g_cond_wait (&priv->conn_cond, &priv->conn_lock); } - g_mutex_unlock (&priv->conn_lock); if (!conn) { if (should_cleanup) @@ -1950,11 +1929,9 @@ async_run_queue (SoupSession *session) if (soup_message_get_method (msg) == SOUP_METHOD_CONNECT) continue; - if (!item->async || - item->async_context != g_main_context_get_thread_default ()) + if (!item->async) continue; - item->async_pending = FALSE; soup_session_process_queue_item (session, item, &should_cleanup, TRUE); } @@ -1972,30 +1949,6 @@ async_run_queue (SoupSession *session) g_object_unref (session); } -static gboolean -idle_run_queue (gpointer user_data) -{ - GWeakRef *wref = user_data; - SoupSession *session; - - session = g_weak_ref_get (wref); - if (!session) - return FALSE; - - async_run_queue (session); - g_object_unref (session); - return FALSE; -} - -static void -idle_run_queue_dnotify (gpointer user_data) -{ - GWeakRef *wref = user_data; - - g_weak_ref_clear (wref); - g_slice_free (GWeakRef, wref); -} - /** * soup_session_requeue_message: * @session: a #SoupSession @@ -2049,42 +2002,8 @@ static void soup_session_kick_queue (SoupSession *session) { SoupSessionPrivate *priv = soup_session_get_instance_private (session); - SoupMessageQueueItem *item; - GHashTable *async_pending; - gboolean have_sync_items = FALSE; - - if (priv->disposed) - return; - async_pending = g_hash_table_new (NULL, NULL); - for (item = soup_message_queue_first (priv->queue); - item; - item = soup_message_queue_next (priv->queue, item)) { - if (item->async) { - GMainContext *context = item->async_context; - - if (!g_hash_table_contains (async_pending, context)) { - if (!item->async_pending) { - GWeakRef *wref = g_slice_new (GWeakRef); - GSource *source; - - g_weak_ref_init (wref, session); - source = soup_add_completion_reffed (context, idle_run_queue, wref, idle_run_queue_dnotify); - g_source_unref (source); - } - g_hash_table_add (async_pending, context); - } - item->async_pending = TRUE; - } else - have_sync_items = TRUE; - } - g_hash_table_unref (async_pending); - - if (have_sync_items) { - g_mutex_lock (&priv->conn_lock); - g_cond_broadcast (&priv->conn_cond); - g_mutex_unlock (&priv->conn_lock); - } + g_source_set_ready_time (priv->queue_source, 0); } /** @@ -2166,7 +2085,6 @@ soup_session_abort (SoupSession *session) } /* Close all idle connections */ - g_mutex_lock (&priv->conn_lock); conns = NULL; g_hash_table_iter_init (&iter, priv->conns); while (g_hash_table_iter_next (&iter, &conn, &host)) { @@ -2180,7 +2098,6 @@ soup_session_abort (SoupSession *session) drop_connection (session, host, conn); } } - g_mutex_unlock (&priv->conn_lock); for (c = conns; c; c = c->next) { soup_connection_disconnect (c->data); @@ -3863,11 +3780,9 @@ steal_connection (SoupSession *session, conn = g_object_ref (item->conn); soup_session_set_item_connection (session, item, NULL); - g_mutex_lock (&priv->conn_lock); host = get_host_for_message (session, item->msg); g_hash_table_remove (priv->conns, conn); drop_connection (session, host, conn); - g_mutex_unlock (&priv->conn_lock); stream = soup_connection_steal_iostream (conn); if (!item->connect_only) diff --git a/libsoup/websocket/soup-websocket-connection.c b/libsoup/websocket/soup-websocket-connection.c index 19b5cd1a..76b929a6 100644 --- a/libsoup/websocket/soup-websocket-connection.c +++ b/libsoup/websocket/soup-websocket-connection.c @@ -131,8 +131,6 @@ typedef struct { gboolean dirty_close; GSource *close_timeout; - GMainContext *main_context; - gboolean io_closing; gboolean io_closed; @@ -266,7 +264,6 @@ soup_websocket_connection_init (SoupWebsocketConnection *self) priv->incoming = g_byte_array_sized_new (1024); g_queue_init (&priv->outgoing); - priv->main_context = g_main_context_ref_thread_default (); } static void @@ -307,7 +304,7 @@ soup_websocket_connection_start_input_source (SoupWebsocketConnection *self) priv->input_source = g_pollable_input_stream_create_source (priv->input, NULL); g_source_set_callback (priv->input_source, (GSourceFunc)on_web_socket_input, self, NULL); - g_source_attach (priv->input_source, priv->main_context); + g_source_attach (priv->input_source, g_main_context_get_thread_default ()); } static void @@ -333,7 +330,7 @@ soup_websocket_connection_start_output_source (SoupWebsocketConnection *self) priv->output_source = g_pollable_output_stream_create_source (priv->output, NULL); g_source_set_callback (priv->output_source, (GSourceFunc)on_web_socket_output, self, NULL); - g_source_attach (priv->output_source, priv->main_context); + g_source_attach (priv->output_source, g_main_context_get_thread_default ()); } static void @@ -445,7 +442,7 @@ close_io_after_timeout (SoupWebsocketConnection *self) g_debug ("waiting %d seconds for peer to close io", timeout); priv->close_timeout = g_timeout_source_new_seconds (timeout); g_source_set_callback (priv->close_timeout, on_timeout_close_io, self, NULL); - g_source_attach (priv->close_timeout, priv->main_context); + g_source_attach (priv->close_timeout, g_main_context_get_thread_default ()); } static void @@ -1441,8 +1438,6 @@ soup_websocket_connection_finalize (GObject *object) g_free (priv->peer_close_data); - g_main_context_unref (priv->main_context); - if (priv->incoming) g_byte_array_free (priv->incoming, TRUE); while (!g_queue_is_empty (&priv->outgoing)) @@ -2169,7 +2164,7 @@ soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self, if (interval > 0) { priv->keepalive_timeout = g_timeout_source_new_seconds (interval); g_source_set_callback (priv->keepalive_timeout, on_queue_ping, self, NULL); - g_source_attach (priv->keepalive_timeout, priv->main_context); + g_source_attach (priv->keepalive_timeout, g_main_context_get_thread_default ()); } } } diff --git a/tests/context-test.c b/tests/context-test.c index 38a303b7..c43fc890 100644 --- a/tests/context-test.c +++ b/tests/context-test.c @@ -128,7 +128,19 @@ idle_start_test1_thread (gpointer user_data) } static void -test1_finished (SoupMessage *msg, +message_send_cb (SoupSession *session, + GAsyncResult *result, + GMainContext *async_context) +{ + GInputStream *stream; + + g_assert_true (async_context == g_main_context_get_thread_default ()); + stream = soup_session_send_finish (session, result, NULL); + g_clear_object (&stream); +} + +static void +message_finished (SoupMessage *msg, GMainLoop *loop) { g_main_loop_quit (loop); @@ -165,8 +177,10 @@ test1_thread (gpointer user_data) debug_printf (1, " queue_message\n"); msg = soup_message_new ("GET", uri); loop = g_main_loop_new (async_context, FALSE); - g_signal_connect (msg, "finished", G_CALLBACK (test1_finished), loop); - soup_session_send_async (session, msg, G_PRIORITY_DEFAULT, NULL, NULL, NULL); + g_signal_connect (msg, "finished", G_CALLBACK (message_finished), loop); + soup_session_send_async (session, msg, G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)message_send_cb, + async_context); g_main_loop_run (loop); /* We need one more iteration, because SoupMessage::finished is emitted * right before the message is unqueued. @@ -203,9 +217,8 @@ do_test2 (void) SoupSession *session; char *uri; SoupMessage *msg; - - g_test_skip ("FIXME"); - return; + GInputStream *stream; + GMainLoop *loop; idle = g_idle_add_full (G_PRIORITY_HIGH, idle_test2_fail, NULL, NULL); @@ -218,7 +231,24 @@ do_test2 (void) debug_printf (1, " send_message\n"); msg = soup_message_new ("GET", uri); -// soup_session_send_message (session, msg); + stream = soup_session_send (session, msg, NULL, NULL); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (stream); + g_object_unref (msg); + + debug_printf (1, " queue_message\n"); + msg = soup_message_new ("GET", uri); + loop = g_main_loop_new (async_context, FALSE); + g_signal_connect (msg, "finished", G_CALLBACK (message_finished), loop); + soup_session_send_async (session, msg, G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)message_send_cb, + async_context); + g_main_loop_run (loop); + /* We need one more iteration, because SoupMessage::finished is emitted + * right before the message is unqueued. + */ + g_main_context_iteration (async_context, TRUE); + g_main_loop_unref (loop); soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); @@ -230,98 +260,6 @@ do_test2 (void) g_main_context_pop_thread_default (async_context); } -#if 0 -static void -request_started (SoupMessage *msg, gpointer user_data) -{ - g_object_set_data (G_OBJECT (msg), "started", GUINT_TO_POINTER (TRUE)); -} - -static void -msg1_got_headers (SoupMessage *msg, gpointer user_data) -{ - GMainLoop *loop = user_data; - - g_main_loop_quit (loop); -} - -static void -multi_msg_finished (SoupSession *session, SoupMessage *msg, gpointer user_data) -{ - GMainLoop *loop = user_data; - - g_object_set_data (G_OBJECT (msg), "finished", GUINT_TO_POINTER (TRUE)); - g_main_loop_quit (loop); -} - -static void -do_multicontext_test (void) -{ - SoupSession *session; - SoupMessage *msg1, *msg2; - GMainContext *context1, *context2; - GMainLoop *loop1, *loop2; - - session = soup_test_session_new (NULL); - - context1 = g_main_context_new (); - loop1 = g_main_loop_new (context1, FALSE); - context2 = g_main_context_new (); - loop2 = g_main_loop_new (context2, FALSE); - - g_main_context_push_thread_default (context1); - msg1 = soup_message_new ("GET", base_uri); - g_object_ref (msg1); - g_signal_connect (msg1, "starting", G_CALLBACK (request_started), NULL); - soup_session_queue_message (session, msg1, multi_msg_finished, loop1); - g_signal_connect (msg1, "got-headers", - G_CALLBACK (msg1_got_headers), loop1); - g_object_set_data (G_OBJECT (msg1), "session", session); - g_main_context_pop_thread_default (context1); - - g_main_context_push_thread_default (context2); - msg2 = soup_message_new ("GET", base_uri); - g_object_ref (msg2); - g_signal_connect (msg2, "starting", G_CALLBACK (request_started), NULL); - soup_session_queue_message (session, msg2, multi_msg_finished, loop2); - g_main_context_pop_thread_default (context2); - - g_main_context_push_thread_default (context1); - g_main_loop_run (loop1); - g_main_context_pop_thread_default (context1); - - if (!g_object_get_data (G_OBJECT (msg1), "started")) - soup_test_assert (FALSE, "msg1 not started"); - if (g_object_get_data (G_OBJECT (msg2), "started")) - soup_test_assert (FALSE, "msg2 started while loop1 was running"); - - g_main_context_push_thread_default (context2); - g_main_loop_run (loop2); - g_main_context_pop_thread_default (context2); - - if (g_object_get_data (G_OBJECT (msg1), "finished")) - soup_test_assert (FALSE, "msg1 finished while loop2 was running"); - if (!g_object_get_data (G_OBJECT (msg2), "finished")) - soup_test_assert (FALSE, "msg2 not finished"); - - g_main_context_push_thread_default (context1); - g_main_loop_run (loop1); - g_main_context_pop_thread_default (context1); - - if (!g_object_get_data (G_OBJECT (msg1), "finished")) - soup_test_assert (FALSE, "msg1 not finished"); - - g_object_unref (msg1); - g_object_unref (msg2); - - soup_test_session_abort_unref (session); - - g_main_loop_unref (loop1); - g_main_loop_unref (loop2); - g_main_context_unref (context1); - g_main_context_unref (context2); -} -#endif int main (int argc, char **argv) { @@ -339,9 +277,6 @@ main (int argc, char **argv) g_test_add_func ("/context/blocking/thread-default", do_test1); g_test_add_func ("/context/nested/thread-default", do_test2); -#if 0 - g_test_add_func ("/context/multiple", do_multicontext_test); -#endif ret = g_test_run (); |