Repository: qtile/qtile

Issue:
Restarting Qtile leaves a traceback
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 72, in unpack
    assert len(data) >= HDRLEN
AssertionError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/qtile-cmd", line 11, in <module>
    load_entry_point('qtile==0.14.2', 'console_scripts', 'qtile-cmd')()
  File "/usr/lib/python3.7/site-packages/libqtile/scripts/qtile_cmd.py", line 185, in main
    ret = run_function(obj, args.function[0], args.args)
  File "/usr/lib/python3.7/site-packages/libqtile/scripts/qtile_cmd.py", line 130, in run_function
    ret = func(*args)
  File "/usr/lib/python3.7/site-packages/libqtile/command.py", line 114, in __call__
    return self.call(self.selectors, self.name, *args, **kwargs)
  File "/usr/lib/python3.7/site-packages/libqtile/command.py", line 251, in call
    state, val = self.client.call((selectors, name, args, kwargs))
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 213, in call
    return self.send(data)
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 206, in send
    self.loop.run_until_complete(asyncio.wait_for(client_proto.reply, timeout=10))
  File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
    return future.result()
  File "/usr/lib/python3.7/asyncio/tasks.py", line 416, in wait_for
    return fut.result()
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 152, in eof_received
    data, _ = _IPC.unpack(self.recv)
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 78, in unpack
    "error reading reply!"
libqtile.ipc.IPCError: error readin


Discussion:
Same thing when trying to restart qtile

```
➜ qtile-cmd -o cmd -f restart
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 72, in unpack
    assert len(data) >= HDRLEN
AssertionError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/sbin/qtile-cmd", line 11, in <module>
    load_entry_point('qtile==0.14.2', 'console_scripts', 'qtile-cmd')()
  File "/usr/lib/python3.7/site-packages/libqtile/scripts/qtile_cmd.py", line 185, in main
    ret = run_function(obj, args.function[0], args.args)
  File "/usr/lib/python3.7/site-packages/libqtile/scripts/qtile_cmd.py", line 130, in run_function
    ret = func(*args)
  File "/usr/lib/python3.7/site-packages/libqtile/command.py", line 114, in __call__
    return self.call(self.selectors, self.name, *args, **kwargs)
  File "/usr/lib/python3.7/site-packages/libqtile/command.py", line 251, in call
    state, val = self.client.call((selectors, name, args, kwargs))
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 211, in call
    return self.send(data)
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 204, in send
    self.loop.run_until_complete(asyncio.wait_for(client_proto.reply, timeout=10))
  File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
    return future.result()
  File "/usr/lib/python3.7/asyncio/tasks.py", line 416, in wait_for
    return fut.result()
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 150, in eof_received
    data, _ = _IPC.unpack(self.recv)
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 78, in unpack
    "error reading reply!"
libqtile.ipc.IPCError: error reading reply! (probably the socket was disconnected)
```
@krive001 Hint: If you put three back ticks („code fences“) before and ofter code, you get an output akin to @Darion's
The error message is pretty explicit: the current socket is closed with the restart, so the IPC client can not get an answer to its request. So everything seems normal to me, but if we want to get rid of the traceback, maybe we should not try to get an answer when restarting Qtile, or only close the socket once we have successfully restarted.
> The error message is pretty explicit: the current socket is closed with the restart, so the IPC client can not get an answer to its request

@ramnes restart does not happen. I'm trying to change config a little (changing a group label, for example), and `qtile-cmd -o cmd -f restart` do nothing. Config changes come only after shutdown and new login.

This is what happens in .local/share/qtile/qtile.log
```
2019-07-14 14:34:02,653 ERROR libqtile manager.py:<lambda>():L274 Got an exception in poll loop
Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 823, in _read_ready__on_eof
    keep_open = self._protocol.eof_received()
  File "/usr/lib/python3.7/site-packages/libqtile/ipc.py", line 271, in eof_received
    self.transport.write(result)
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 842, in write
    raise RuntimeError('Cannot call write() after write_eof()')
RuntimeError: Cannot call write() after write_eof()

```
Update: non-working restart command is not connected with this tracebacks. This was because of unicode symbols in group labels.
I'm marking this as enhancement if someone want to either get rid of the traceback when restarting, or find a way to keep the socket alive across the restart.

Resolving patch:
diff --git a/libqtile/ipc.py b/libqtile/ipc.py
--- a/libqtile/ipc.py
+++ b/libqtile/ipc.py
@@ -195,11 +195,6 @@ async def _server_callback(
         except IPCError:
             logger.warn("Invalid data received, closing connection")
         else:
-            if req[1] == "restart":
-                # if we are going to restart, close the connection first, as we won't be back
-                logger.debug("Closing connection on restart")
-                writer.write_eof()
-
             rep = self.handler(req)
 
             result = _IPC.pack(rep, is_json=is_json)


Test patch: