summaryrefslogtreecommitdiff
path: root/libsoup
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2021-06-11 12:04:10 +0200
committerCarlos Garcia Campos <cgarcia@igalia.com>2021-06-11 12:04:10 +0200
commit890766793f9d349c54a7437b32dba9ae79690579 (patch)
treed646dfa424125324c60b707a6b62c398c1e68210 /libsoup
parent4ab3878f8a42b4b145fffde49d42d915bd97a3c1 (diff)
downloadlibsoup-890766793f9d349c54a7437b32dba9ae79690579.tar.gz
Wait until IO finished before re-starting a request
In case of restarting it can happen that the new request is started before the previous one is fully completed. This is because restart is scheduled on SoupMessage::got-body that happens right before the stream is closed and the IO finished. In HTTP/1.x this is possible if a new request is made in got-body callback, for example. In HTTP/2 is easier to reproduce because we emit SoupMessage::got-body right after SoupClientInputStream::eof. This patch adds an intermediate state SOUP_MESSAGE_REQUEUED set by soup_session_requeue_item(). The transition to SOUP_MESSAGE_RESTARTING happens when the message IO completes to ensure the restarted request starts when message no longer has an active IO.
Diffstat (limited to 'libsoup')
-rw-r--r--libsoup/http1/soup-client-message-io-http1.c2
-rw-r--r--libsoup/soup-message-queue-item.h1
-rw-r--r--libsoup/soup-session.c9
3 files changed, 11 insertions, 1 deletions
diff --git a/libsoup/http1/soup-client-message-io-http1.c b/libsoup/http1/soup-client-message-io-http1.c
index ab589e43..46029612 100644
--- a/libsoup/http1/soup-client-message-io-http1.c
+++ b/libsoup/http1/soup-client-message-io-http1.c
@@ -1043,6 +1043,8 @@ soup_client_message_io_http1_send_item (SoupClientMessageIO *iface,
#ifdef HAVE_SYSPROF
msg_io->begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME;
#endif
+ if (io->msg_io)
+ g_warn_if_reached ();
io->msg_io = msg_io;
io->is_reusable = FALSE;
diff --git a/libsoup/soup-message-queue-item.h b/libsoup/soup-message-queue-item.h
index cb483668..9a958342 100644
--- a/libsoup/soup-message-queue-item.h
+++ b/libsoup/soup-message-queue-item.h
@@ -20,6 +20,7 @@ typedef enum {
SOUP_MESSAGE_READY,
SOUP_MESSAGE_RUNNING,
SOUP_MESSAGE_CACHED,
+ SOUP_MESSAGE_REQUEUED,
SOUP_MESSAGE_RESTARTING,
SOUP_MESSAGE_FINISHING,
SOUP_MESSAGE_FINISHED
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index d1df9226..7380ff0a 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1205,7 +1205,7 @@ soup_session_requeue_item (SoupSession *session,
retval = FALSE;
} else {
item->resend_count++;
- item->state = SOUP_MESSAGE_RESTARTING;
+ item->state = SOUP_MESSAGE_REQUEUED;
retval = TRUE;
}
@@ -1590,6 +1590,9 @@ message_completed (SoupMessage *msg, SoupMessageIOCompletion completion, gpointe
return;
}
+ if (item->state == SOUP_MESSAGE_REQUEUED)
+ item->state = SOUP_MESSAGE_RESTARTING;
+
if (item->state != SOUP_MESSAGE_RESTARTING) {
item->state = SOUP_MESSAGE_FINISHING;
@@ -1646,6 +1649,9 @@ tunnel_message_completed (SoupMessage *msg, SoupMessageIOCompletion completion,
SoupSession *session = tunnel_item->session;
guint status;
+ if (tunnel_item->state == SOUP_MESSAGE_REQUEUED)
+ tunnel_item->state = SOUP_MESSAGE_RESTARTING;
+
if (tunnel_item->state == SOUP_MESSAGE_RESTARTING) {
soup_message_restarted (msg);
if (soup_message_get_connection (tunnel_item->msg)) {
@@ -2028,6 +2034,7 @@ soup_session_process_queue_item (SoupSession *session,
case SOUP_MESSAGE_CACHED:
case SOUP_MESSAGE_TUNNELING:
+ case SOUP_MESSAGE_REQUEUED:
/* Will be handled elsewhere */
return;