Shouldn't we add a new CLOSING state in H2 ?
Willy Tarreau <w@1wt.eu> Thu, 24 January 2019 14:10 UTC
Return-Path: <ietf-http-wg-request+bounce-httpbisa-archive-bis2juki=lists.ie@listhub.w3.org>
X-Original-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Delivered-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 13995124BE5 for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Thu, 24 Jan 2019 06:10:11 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.9
X-Spam-Level:
X-Spam-Status: No, score=-2.9 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.001, MAILING_LIST_MULTI=-1, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gDdce04e0aiP for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Thu, 24 Jan 2019 06:10:08 -0800 (PST)
Received: from frink.w3.org (frink.w3.org [IPv6:2603:400a:ffff:804:801e:34:0:38]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 7B94E1228B7 for <httpbisa-archive-bis2Juki@lists.ietf.org>; Thu, 24 Jan 2019 06:10:08 -0800 (PST)
Received: from lists by frink.w3.org with local (Exim 4.89) (envelope-from <ietf-http-wg-request@listhub.w3.org>) id 1gmff8-0008GI-2o for ietf-http-wg-dist@listhub.w3.org; Thu, 24 Jan 2019 14:07:22 +0000
Resent-Date: Thu, 24 Jan 2019 14:07:22 +0000
Resent-Message-Id: <E1gmff8-0008GI-2o@frink.w3.org>
Received: from mimas.w3.org ([2603:400a:ffff:804:801e:34:0:4f]) by frink.w3.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from <w@1wt.eu>) id 1gmff6-0008Ff-HB for ietf-http-wg@listhub.w3.org; Thu, 24 Jan 2019 14:07:20 +0000
Received: from wtarreau.pck.nerim.net ([62.212.114.60] helo=1wt.eu) by mimas.w3.org with esmtp (Exim 4.89) (envelope-from <w@1wt.eu>) id 1gmff5-00042O-3M for ietf-http-wg@w3.org; Thu, 24 Jan 2019 14:07:20 +0000
Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id x0OE6uuK021003 for ietf-http-wg@w3.org; Thu, 24 Jan 2019 15:06:56 +0100
Date: Thu, 24 Jan 2019 15:06:56 +0100
From: Willy Tarreau <w@1wt.eu>
To: ietf-http-wg@w3.org
Message-ID: <20190124140656.GC20924@1wt.eu>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
User-Agent: Mutt/1.6.1 (2016-04-27)
X-W3C-Hub-Spam-Status: No, score=-6.8
X-W3C-Hub-Spam-Report: AWL=1.077, BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, W3C_AA=-1, W3C_IRA=-1, W3C_IRR=-3, W3C_WL=-1
X-W3C-Scan-Sig: mimas.w3.org 1gmff5-00042O-3M f66c2c49bac9e10a6ffac34e83ee2a0a
X-Original-To: ietf-http-wg@w3.org
Subject: Shouldn't we add a new CLOSING state in H2 ?
Archived-At: <https://www.w3.org/mid/20190124140656.GC20924@1wt.eu>
Resent-From: ietf-http-wg@w3.org
X-Mailing-List: <ietf-http-wg@w3.org> archive/latest/36291
X-Loop: ietf-http-wg@w3.org
Resent-Sender: ietf-http-wg-request@w3.org
Precedence: list
List-Id: <ietf-http-wg.w3.org>
List-Help: <https://www.w3.org/Mail/>
List-Post: <mailto:ietf-http-wg@w3.org>
List-Unsubscribe: <mailto:ietf-http-wg-request@w3.org?subject=unsubscribe>
Hi, I've recently got an interesting problem reported about haproxy's H2 implementation which could possibly affect other implementations to some extents. At least I think it is in part related to the issue about the dependency tree being racy here : https://github.com/httpwg/http-extensions/issues/751 The problem is that from time to time some people are getting some TCP resets at the end of a transfer during an haproxy process restart. I analysed the situation a little bit and figured what can cause this. In short, the client sends a HEADERS frame with ES flag set. The stream is seen as half-closed(remote). Let's say it's a GET for a large object. Haproxy passes it to the server, receives the response and starts to stream the response to the client. During the transfer, haproxy gets a signal indicating that it's going to be reloaded and must terminate its connections ASAP. It then sends a GOAWAY with ID=1 to the client along with the data which continue to be streamed, informing the client that it doesn't want to receive new requests on this connection. Once it finishes to transfer the large response, the last DATA frame carries the ES flag, and the stream switches to CLOSED. Since the connection no longer has any stream and already sent a GOAWAY a long time ago to perform a graceful shutdown, it can naturally close. Except that the client continues to send WINDOW_UPDATE frames back... These frames will eventually meet a closed TCP connection, resulting in a TCP reset often causing some payload truncation, especially with the data still lying in the system's socket buffers (hence why it mosly affects large objects). We could imagine a lot of dirty time-based workarounds for this, but they would only steer the problem to another area. On TCP an exactly similar situation exists and is covered by the LAST_ACK state : the connection remains in LAST_ACK until the FIN is acknowledged. In my opinion a good approach here would consist in implementing a CLOSING state before the CLOSED state as long as we know we have data in flight, and only switching to CLOSED once enough WINDOW_UPDATE were received. The frames causing this problem are essentially DATA frames, because these ones lead to WINDOW_UPDATE frames being sent back. These ones are almost ACKs. I'm saying "almost" because they can also be used to bump the window at once. But at least we know we're expected to continue to receive such frames until the window has not grown by at least the number of bytes sent since the last update. And in all situations where the stream window doesn't change it would even be an exact match. This could also help address some of the races that exist in error handling for frames received on closed streams since in general the stream is not available anymore to know whether it was closed with ES or RST_STREAM for example. A possible improvement to the approach above could be to add a new setting mentioning that WINDOW_UPDATE=0 is supported, and we'd use this to indicate that we've received the ES bit or RST_STREAM for the associated stream. It could possibly even be extended to the connection itself, by indicating that we've reached the end of the last stream advertised in GOAWAY since in this case we know the other side is not going to send anything anymore. Does anyone here think there would be any interest in working on such a thing ? I'm personally interested in trying to stuff something like this into haproxy. But while the passive monitoring of WINDOW_UPDATE might work without cooperation from the other side, something more robust like an extension for WU=0 would need support from other agents, so if nobody is interested it's not worth working on it. That's why I'm interested in gathering opinions. Thanks, Willy
- Shouldn't we add a new CLOSING state in H2 ? Willy Tarreau
- Re: Shouldn't we add a new CLOSING state in H2 ? Alcides Viamontes E
- Re: Shouldn't we add a new CLOSING state in H2 ? Willy Tarreau
- Re: Shouldn't we add a new CLOSING state in H2 ? Willy Tarreau
- Re: Shouldn't we add a new CLOSING state in H2 ? Patrick McManus
- Re: Shouldn't we add a new CLOSING state in H2 ? Willy Tarreau
- Re: Shouldn't we add a new CLOSING state in H2 ? Martin Thomson
- Re: Shouldn't we add a new CLOSING state in H2 ? Patrick McManus
- Re: Shouldn't we add a new CLOSING state in H2 ? Martin Thomson