fix #3780
diff --git a/mitmproxy/proxy/protocol/http2.py b/mitmproxy/proxy/protocol/http2.py
index a5870e6c8e..89e652e3d9 100644
--- a/mitmproxy/proxy/protocol/http2.py
+++ b/mitmproxy/proxy/protocol/http2.py
@@ -87,6 +87,18 @@ class Http2Layer(base.Layer):
         # mypy type hints
         client_conn: connections.ClientConnection = None
 
+    class H2ConnLogger:
+        def __init__(self, name, log):
+            self.name = name
+            self.log = log
+
+        def debug(self, fmtstr, *args):
+            msg = "H2Conn {}: {}".format(self.name, fmtstr % args)
+            self.log(msg, "debug")
+
+        def trace(self, fmtstr, *args):
+            pass
+
     def __init__(self, ctx, mode: str) -> None:
         super().__init__(ctx)
         self.mode = mode
@@ -98,7 +110,8 @@ def __init__(self, ctx, mode: str) -> None:
             client_side=False,
             header_encoding=False,
             validate_outbound_headers=False,
-            validate_inbound_headers=False)
+            validate_inbound_headers=False,
+            logger=self.H2ConnLogger("client", self.log))
         self.connections[self.client_conn] = SafeH2Connection(self.client_conn, config=config)
 
     def _initiate_server_conn(self):
@@ -107,7 +120,8 @@ def _initiate_server_conn(self):
                 client_side=True,
                 header_encoding=False,
                 validate_outbound_headers=False,
-                validate_inbound_headers=False)
+                validate_inbound_headers=False,
+                logger=self.H2ConnLogger("server", self.log))
             self.connections[self.server_conn] = SafeH2Connection(self.server_conn, config=config)
         self.connections[self.server_conn].initiate_connection()
         self.server_conn.send(self.connections[self.server_conn].data_to_send())
@@ -195,10 +209,12 @@ def _handle_data_received(self, eid, event, source_conn):
         else:
             self.streams[eid].data_queue.put(event.data)
             self.streams[eid].queued_data_length += len(event.data)
-            self.connections[source_conn].safe_acknowledge_received_data(
-                event.flow_controlled_length,
-                event.stream_id
-            )
+
+        # always acknowledge receved data with a WINDOW_UPDATE frame
+        self.connections[source_conn].safe_acknowledge_received_data(
+            event.flow_controlled_length,
+            event.stream_id
+        )
         return True
 
     def _handle_stream_ended(self, eid):
@@ -461,7 +477,7 @@ def raise_zombie(self, pre_command=None):  # pragma: no cover
         if self.zombie is not None or connection_closed:
             if pre_command is not None:
                 pre_command()
-            raise exceptions.Http2ZombieException("Connection already dead")
+            raise exceptions.Http2ZombieException("Connection or stream already dead: {}, {}".format(self.zombie, connection_closed))
 
     @detect_zombie_stream
     def read_request_headers(self, flow):
@@ -643,7 +659,8 @@ def run(self):
         try:
             layer()
         except exceptions.Http2ZombieException:  # pragma: no cover
-            pass
+            # zombies can be safely terminated - no need to kill them twice
+            return
         except exceptions.ProtocolException as e:  # pragma: no cover
             self.log(repr(e), "info")
         except exceptions.SetServerNotAllowedException as e:  # pragma: no cover
diff --git a/setup.py b/setup.py
index 690a433a18..c5edee18c8 100644
--- a/setup.py
+++ b/setup.py
@@ -68,7 +68,7 @@
         "click>=7.0,<8",
         "cryptography>=2.1.4,<2.5",
         "flask>=1.1.1,<1.2",
-        "h2>=3.0.1,<4",
+        "h2>=3.2.0,<4",
         "hyperframe>=5.1.0,<6",
         "kaitaistruct>=0.7,<0.9",
         "ldap3>=2.6.1,<2.7",

The main fix is bumping the hyper-h2 dependency.
The rest of the changes are just additional debug enhancements.

fixes #3780