Repository: mitmproxy/mitmproxy

Issue:
StackTrace printed if you quit mitmproxy and any flow is in intercept mode
##### Steps to reproduce the problem:
1. Launch mitmproxy
2. intercept any request
3. quit mitmproxy while the request still intercept
##### What is the expected behavior?

Did not expect the stacktrace ... earlier it used to be no such error
##### What went wrong?

```
Traceback (most recent call last):
  File "/Users/manish/Work/mitmproxy/venv/bin/mitmproxy", line 11, in <module>
    load_entry_point('mitmproxy', 'console_scripts', 'mitmproxy')()
  File "/Users/manish/Work/mitmproxy/mitmproxy/main.py", line 80, in mitmproxy
    m.run()
  File "/Users/manish/Work/mitmproxy/mitmproxy/console/master.py", line 495, in run
    self.shutdown()
  File "/Users/manish/Work/mitmproxy/mitmproxy/console/master.py", line 647, in shutdown
    self.state.killall(self)
  File "/Users/manish/Work/mitmproxy/mitmproxy/flow/state.py", line 269, in killall
    self.flows.kill_all(master)
  File "/Users/manish/Work/mitmproxy/mitmproxy/flow/state.py", line 182, in kill_all
    f.kill(master)
  File "/Users/manish/Work/mitmproxy/mitmproxy/models/flow.py", line 176, in kill
    master.error(self)
  File "/Users/manish/Work/mitmproxy/mitmproxy/controller.py", line 238, in wrapper
    ret = f(master, message)
  File "/Users/manish/Work/mitmproxy/mitmproxy/console/master.py", line 692, in error
    self.process_flow(f)
  File "/Users/manish/Work/mitmproxy/mitmproxy/console/master.py", line 681, in process_flow
    f.intercept(self)
  File "/Users/manish/Work/mitmproxy/mitmproxy/models/flow.py", line 186, in intercept
    self.reply.take()
  File "/Users/manish/Work/mitmproxy/mitmproxy/controller.py", line 314, in take
    raise exceptions.ControlException("Reply is {}, but expected it to be handled.".format(self.state))
mitmproxy.exceptions.ControlException: Reply is committed, but expected it to be handled.
```
##### Any other comments? What have you tried so far?

This may result in problems in saving flows to file? if any request is in intercept mode it might cause abort at that point .. only flows till that point gets saved.. i think, also, har dump may get problem due to this.. 

---

Mitmproxy Version: head, master
Operating System: mac

<!-- Please use the mitmproxy forums (https://discourse.mitmproxy.org/) for support/how-to questions. Thanks! :) -->



Discussion:
Thanks for the great bug report!


Resolving patch:
diff --git a/mitmproxy/flow.py b/mitmproxy/flow.py
--- a/mitmproxy/flow.py
+++ b/mitmproxy/flow.py
@@ -2,6 +2,7 @@
 import copy
 import uuid
 
+from mitmproxy import controller  # noqa
 from mitmproxy import stateobject
 from mitmproxy import connections
 from mitmproxy import version
@@ -80,7 +81,7 @@ def __init__(
         self.error = None  # type: Optional[Error]
         self.intercepted = False  # type: bool
         self._backup = None  # type: Optional[Flow]
-        self.reply = None
+        self.reply = None  # type: Optional[controller.Reply]
         self.marked = False  # type: bool
 
     _stateobject_attributes = dict(
diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py
--- a/mitmproxy/tools/console/master.py
+++ b/mitmproxy/tools/console/master.py
@@ -659,11 +659,10 @@ def refresh_focus(self):
             )
 
     def process_flow(self, f):
-        should_intercept = any(
-            [
-                self.state.intercept and flowfilter.match(self.state.intercept, f) and not f.request.is_replay,
-                f.intercepted,
-            ]
+        should_intercept = (
+            self.state.intercept and flowfilter.match(self.state.intercept, f)
+            and not f.request.is_replay
+            and f.reply.state == "handled"
         )
         if should_intercept:
             f.intercept(self)
diff --git a/mitmproxy/tools/web/master.py b/mitmproxy/tools/web/master.py
--- a/mitmproxy/tools/web/master.py
+++ b/mitmproxy/tools/web/master.py
@@ -9,6 +9,7 @@
 from mitmproxy import addons
 from mitmproxy import controller
 from mitmproxy import exceptions
+from mitmproxy import flowfilter
 from mitmproxy.addons import state
 from mitmproxy import options
 from mitmproxy import master
@@ -179,8 +180,12 @@ def run(self):  # pragma: no cover
             self.shutdown()
 
     def _process_flow(self, f):
-        if self.state.intercept and self.state.intercept(
-                f) and not f.request.is_replay:
+        should_intercept = (
+            self.state.intercept and flowfilter.match(self.state.intercept, f)
+            and not f.request.is_replay
+            and f.reply.state == "handled"
+        )
+        if should_intercept:
             f.intercept(self)
         return f
 


Test patch: