diff --git a/docs/releases.rst b/docs/releases.rst
index ea32618..517a41c 100644
--- a/docs/releases.rst
+++ b/docs/releases.rst
@@ -18,6 +18,7 @@ See also :ref:`api_stability`.
 `git main <https://github.com/meejah/txtorcon>`_ *will likely become v23.6.0*
 
  * Fix test-failures on Python 3.12
+ * Particular GETINFO hanging (`#389 <https://github.com/meejah/txtorcon/issues/389>`_)
 
 
 v23.5.0
diff --git a/txtorcon/torcontrolprotocol.py b/txtorcon/torcontrolprotocol.py
index 887bd0a..e882160 100644
--- a/txtorcon/torcontrolprotocol.py
+++ b/txtorcon/torcontrolprotocol.py
@@ -232,6 +232,12 @@ class TorControlProtocol(LineOnlyReceiver):
     :class:`txtorcon.TorState`, which is also the place to go if you
     wish to add your own stream or circuit listeners.
     """
+    # override Twisted's LineOnlyReceiver maximum line-length. At
+    # least "GETINFO md/id/X" for some Xse exceeds 16384 (2**14, the
+    # default) and thus causes the control connection to
+    # fail. control.c defines MAX_COMMAND_LINE_LENGTH as 1024*1024 so
+    # we use that
+    MAX_LENGTH = 2 ** 20
 
     def __init__(self, password_function=None):
         """
@@ -274,11 +280,6 @@ class TorControlProtocol(LineOnlyReceiver):
         :func:`when_disconnected` instead)
         """
 
-        self._when_disconnected = SingleObserver()
-        """
-        Internal use. A :class:`SingleObserver` for when_disconnected()
-        """
-
         self._when_disconnected = SingleObserver()
         """
         Private. See :func:`.when_disconnected`
@@ -356,7 +357,7 @@ class TorControlProtocol(LineOnlyReceiver):
         self.stop_debug()
 
     def start_debug(self):
-        self.debuglog = open('txtorcon-debug.log', 'w')
+        self.debuglog = open('txtorcon-debug.log', 'wb')
 
     def stop_debug(self):
         def noop(*args, **kw):
@@ -692,10 +693,14 @@ class TorControlProtocol(LineOnlyReceiver):
     def connectionLost(self, reason):
         "Protocol API"
         txtorlog.msg('connection terminated: ' + str(reason))
-        if reason.check(ConnectionDone):
-            self._when_disconnected.fire(self)
-        else:
-            self._when_disconnected.fire(reason)
+        self._when_disconnected.fire(
+            Failure(
+                TorDisconnectError(
+                    text="Tor connection terminated",
+                    error=reason,
+                )
+            )
+        )
 
         # ...and this is why we don't do on_disconnect = Deferred() :(
         # and instead should have had on_disconnect() method that
@@ -712,8 +717,10 @@ class TorControlProtocol(LineOnlyReceiver):
             else:
                 self.on_disconnect.errback(reason)
         self.on_disconnect = None
-        self._when_disconnected.fire(self)
+
         outstanding = [self.command] + self.commands if self.command else self.commands
+        self.command = None
+        self.defer = None
         for d, cmd, cmd_arg in outstanding:
             if not d.called:
                 d.errback(
@@ -754,6 +761,10 @@ class TorControlProtocol(LineOnlyReceiver):
         if len(self.commands):
             self.command = self.commands.pop(0)
             (d, cmd, cmd_arg) = self.command
+
+            if self._when_disconnected.already_fired(d):
+                return
+
             self.defer = d
 
             self.debuglog.write(cmd + b'\n')
diff --git a/txtorcon/util.py b/txtorcon/util.py
index 4b772e3..406a0f5 100644
--- a/txtorcon/util.py
+++ b/txtorcon/util.py
@@ -473,6 +473,19 @@ class SingleObserver(object):
         self._observers = []
         self._fired = self._NotFired
 
+    def has_fired(self):
+        return self._fired is not self._NotFired
+
+    def already_fired(self, d):
+        """
+        If we have already fired, callback `d` with our result.
+        :returns bool: True if we already fired, False otherwise
+        """
+        if self.has_fired():
+            d.callback(self._fired)
+            return True
+        return False
+
     def when_fired(self):
         d = defer.Deferred()
         if self._fired is not self._NotFired:

diff --git a/test/test_torcontrolprotocol.py b/test/test_torcontrolprotocol.py
index 23ddeec..e15bdf0 100644
--- a/test/test_torcontrolprotocol.py
+++ b/test/test_torcontrolprotocol.py
@@ -226,7 +226,7 @@ class DisconnectionTests(unittest.TestCase):
         it_was_called.yes = False
 
         d = self.protocol.when_disconnected()
-        d.addCallback(it_was_called)
+        d.addBoth(it_was_called)
         f = failure.Failure(error.ConnectionDone("It's all over"))
         self.protocol.connectionLost(f)
         self.assertTrue(it_was_called.yes)
@@ -284,6 +284,31 @@ class DisconnectionTests(unittest.TestCase):
         self.protocol.connectionLost(f)
         self.assertEqual(it_was_called.count, 2)
 
+    def test_disconnect_subsequent_commands(self):
+        """
+        commands issued after disconnect should errback
+        """
+
+        def it_was_called(f):
+            str(f)
+            it_was_called.count += 1
+            return None
+        it_was_called.count = 0
+
+        # one outstanding command
+        d0 = self.protocol.queue_command("some command0")
+        d0.addErrback(it_was_called)
+        self.protocol.on_disconnect.addErrback(lambda _: None)
+
+        f = failure.Failure(RuntimeError("The thing didn't do the stuff."))
+        self.protocol.connectionLost(f)
+
+        # one command issued _after_ we've disconnected
+        d1 = self.protocol.queue_command("some command1")
+        d1.addErrback(it_was_called)
+
+        self.assertEqual(it_was_called.count, 2)
+
 
 class ProtocolTests(unittest.TestCase):
 

When tor process exits unexpectedly tor.protocol.get_info hangs
Here is a minimal reproduction for this issue:

```python
from twisted.internet.task import react
from twisted.internet.defer import ensureDeferred

import txtorcon

EXIT_RELAY_FP = [
'130CFCF38BA3327E3001A1DB2A4B5ACBDAE248D9', # this triggers the getinfo fail

'127F6358F68FFB7E437DBA51D6D4DAC47B9F78A7',
]

async def main(reactor):
        try:
            tor = await txtorcon.launch(
                reactor,
                kill_on_stderr=False,
                progress_updates=lambda x, y, z: print(f"{x}%: {y} - {z}"),
            )
        except Exception as exc:
            print(f"FAILED to start tor {exc}")
            return

        state = await tor.create_state()
        for exit_fp in EXIT_RELAY_FP:
            print(f"doing {exit_fp}")
            try:
                print("calling GETINFO")
                info = await tor.protocol.get_info("md/id/" + exit_fp)
                print(f"got {info}")
            except Exception as exc:
                print(f"FAILED to get info for {exit_fp} {exc}")

@react
def _main(reactor):
    return ensureDeferred(main(reactor))
```

You can see that the last log lines are:
```
doing 130CFCF38BA3327E3001A1DB2A4B5ACBDAE248D9
calling GETINFO
FAILED to get info for 130CFCF38BA3327E3001A1DB2A4B5ACBDAE248D9 Tor unexpectedly disconnected while running: GETINFO md/id/130CFCF38BA3327E3001A1DB2A4B5ACBDAE248D9
doing 127F6358F68FFB7E437DBA51D6D4DAC47B9F78A7
calling GETINFO
Unhandled Error
Traceback (most recent call last):
Failure: builtins.RuntimeError: Tor exited with error-code 0
```

Where we are waiting on the `tor.protocol.get_info("md/id/" + exit_fp)` call.

I would expect to either get an errback, because the process is dead or have some other way to tell that I should not be calling it.

It would also be nice to be able to somehow know that tor has exited this way, as it's currently not possible to listen for the "tor exited" event.

This probably is also a tor bug, as it should not happen that the tor process exits when issuing this specific get_info command.
test/test_torcontrolprotocol.py::DisconnectionTests::test_disconnect_subsequent_commands
test/test_torcontrolprotocol.py::InterfaceTests::test_implements test/test_torcontrolprotocol.py::InterfaceTests::test_object_implements test/test_torcontrolprotocol.py::LogicTests::test_set_conf_wrong_args test/test_torcontrolprotocol.py::FactoryTests::test_create test/test_torcontrolprotocol.py::AuthenticationTests::test_authenticate_cookie test/test_torcontrolprotocol.py::AuthenticationTests::test_authenticate_no_password test/test_torcontrolprotocol.py::AuthenticationTests::test_authenticate_null test/test_torcontrolprotocol.py::AuthenticationTests::test_authenticate_password test/test_torcontrolprotocol.py::AuthenticationTests::test_authenticate_password_deferred test/test_torcontrolprotocol.py::AuthenticationTests::test_authenticate_password_deferred_but_no_password test/test_torcontrolprotocol.py::AuthenticationTests::test_authenticate_password_not_bytes test/test_torcontrolprotocol.py::DisconnectionTests::test_disconnect_callback test/test_torcontrolprotocol.py::DisconnectionTests::test_disconnect_errback test/test_torcontrolprotocol.py::DisconnectionTests::test_disconnect_outstanding_commands test/test_torcontrolprotocol.py::DisconnectionTests::test_when_disconnect test/test_torcontrolprotocol.py::DisconnectionTests::test_when_disconnect_error test/test_torcontrolprotocol.py::ProtocolTests::test_650_after_authenticate test/test_torcontrolprotocol.py::ProtocolTests::test_addevent test/test_torcontrolprotocol.py::ProtocolTests::test_async test/test_torcontrolprotocol.py::ProtocolTests::test_async_multiline test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_cookie_without_reading test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_dont_send_cookiefile test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_fail test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_no_auth_line test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_not_enough_cookie_data test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_not_enough_safecookie_data test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_password_when_cookie_unavailable test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_password_when_safecookie_unavailable test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_safecookie test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_safecookie_wrong_hash test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_unexisting_cookie_file test/test_torcontrolprotocol.py::ProtocolTests::test_authenticate_unexisting_safecookie_file test/test_torcontrolprotocol.py::ProtocolTests::test_bootstrap_callback test/test_torcontrolprotocol.py::ProtocolTests::test_bootstrap_tor_does_not_support_signal_names test/test_torcontrolprotocol.py::ProtocolTests::test_continuation_line test/test_torcontrolprotocol.py::ProtocolTests::test_debug test/test_torcontrolprotocol.py::ProtocolTests::test_dot test/test_torcontrolprotocol.py::ProtocolTests::test_eventlistener test/test_torcontrolprotocol.py::ProtocolTests::test_eventlistener_error test/test_torcontrolprotocol.py::ProtocolTests::test_getconf test/test_torcontrolprotocol.py::ProtocolTests::test_getconf_raw test/test_torcontrolprotocol.py::ProtocolTests::test_getconf_single test/test_torcontrolprotocol.py::ProtocolTests::test_getinfo test/test_torcontrolprotocol.py::ProtocolTests::test_getinfo_for_descriptor test/test_torcontrolprotocol.py::ProtocolTests::test_getinfo_incremental test/test_torcontrolprotocol.py::ProtocolTests::test_getinfo_incremental_continuation test/test_torcontrolprotocol.py::ProtocolTests::test_getinfo_multiline test/test_torcontrolprotocol.py::ProtocolTests::test_getinfo_one_line test/test_torcontrolprotocol.py::ProtocolTests::test_getinfo_single test/test_torcontrolprotocol.py::ProtocolTests::test_minus_line_no_command test/test_torcontrolprotocol.py::ProtocolTests::test_multiline_plus test/test_torcontrolprotocol.py::ProtocolTests::test_multiline_plus_embedded_equals test/test_torcontrolprotocol.py::ProtocolTests::test_newdesc test/test_torcontrolprotocol.py::ProtocolTests::test_notify_after_getinfo test/test_torcontrolprotocol.py::ProtocolTests::test_notify_error test/test_torcontrolprotocol.py::ProtocolTests::test_plus_line_no_command test/test_torcontrolprotocol.py::ProtocolTests::test_quit test/test_torcontrolprotocol.py::ProtocolTests::test_remove_eventlistener test/test_torcontrolprotocol.py::ProtocolTests::test_remove_eventlistener_multiple test/test_torcontrolprotocol.py::ProtocolTests::test_response_with_no_request test/test_torcontrolprotocol.py::ProtocolTests::test_setconf test/test_torcontrolprotocol.py::ProtocolTests::test_setconf_multi test/test_torcontrolprotocol.py::ProtocolTests::test_setconf_with_space test/test_torcontrolprotocol.py::ProtocolTests::test_signal test/test_torcontrolprotocol.py::ProtocolTests::test_signal_error test/test_torcontrolprotocol.py::ProtocolTests::test_statemachine_broadcast_no_code test/test_torcontrolprotocol.py::ProtocolTests::test_statemachine_broadcast_unknown_code test/test_torcontrolprotocol.py::ProtocolTests::test_statemachine_continuation test/test_torcontrolprotocol.py::ProtocolTests::test_statemachine_is_finish test/test_torcontrolprotocol.py::ProtocolTests::test_statemachine_multiline test/test_torcontrolprotocol.py::ProtocolTests::test_statemachine_singleline test/test_torcontrolprotocol.py::ProtocolTests::test_twocommands test/test_torcontrolprotocol.py::ParseTests::test_circuit_status test/test_torcontrolprotocol.py::ParseTests::test_default_keywords test/test_torcontrolprotocol.py::ParseTests::test_keywords test/test_torcontrolprotocol.py::ParseTests::test_keywords_mutli_equals test/test_torcontrolprotocol.py::ParseTests::test_multientry_keywords_2 test/test_torcontrolprotocol.py::ParseTests::test_multientry_keywords_3 test/test_torcontrolprotocol.py::ParseTests::test_multientry_keywords_4 test/test_torcontrolprotocol.py::ParseTests::test_multiline_keywords test/test_torcontrolprotocol.py::ParseTests::test_multiline_keywords_with_spaces test/test_torcontrolprotocol.py::ParseTests::test_network_status test/test_torcontrolprotocol.py::ParseTests::test_unquoted_keywords test/test_torcontrolprotocol.py::ParseTests::test_unquoted_keywords_empty test/test_torcontrolprotocol.py::ParseTests::test_unquoted_keywords_singlequote