summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2021-02-25 11:45:33 +0100
committerCarlos Garcia Campos <cgarcia@igalia.com>2021-02-25 15:57:51 +0100
commit69dc2314e881487cbf8147f6c48b9e8d2e258358 (patch)
tree55e16bf48b3428c3fa52f798b1f16741bd865c18
parentb45a7f2e0f80af10915be982f28c4888b18fd954 (diff)
downloadlibsoup-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.c33
-rw-r--r--libsoup/server/soup-server-io.c14
-rw-r--r--libsoup/soup-logger.c23
-rw-r--r--libsoup/soup-message-io-data.c2
-rw-r--r--libsoup/soup-message-io-data.h1
-rw-r--r--libsoup/soup-message-io.c9
-rw-r--r--libsoup/soup-message-queue.c31
-rw-r--r--libsoup/soup-message-queue.h2
-rw-r--r--libsoup/soup-session.c175
-rw-r--r--libsoup/websocket/soup-websocket-connection.c13
-rw-r--r--tests/context-test.c139
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 ();