Repository: qtile/qtile

Issue:
`loginctrl terminate-session ...` leaves qtile in a weird state
# Issue description

When issuing `loginctrl terminate-session $XDG_SESSION_ID`, in the past I logged out of qtile. With any of the recent builds, however, what happens is this: qtile and all applications are killed/shutdown (so far, so good), but then qtile restarts immediately. I am not logged out (yet), but I end up in a weird state: None of my autostart applications are running (so qtile only *re*started instead of fully starting again, I assume) and I cannot log out or reboot now without considerable effort.
After about a minute of this spooky state I am finally logged out properly.

I can't really track down since when this has been happening or whether it might be related to a change in systemd even. But I know that there has been some work put into restarting qtile, so this might be a legit issue.


# Qtile version

Any recent commit upwards of 0.17 I tested showed this behaviour. I didn't go back any further, though (couldn't, really, since at some point my config will certainly break).


# Stack traces

I shortened the log output quite a bit, since it seemed to repeat a lot:

```log
2021-02-25 22:28:05,017 ERROR libqtile base.py:_wrapper():L300 got exception from widget timer
Traceback (most recent call last):
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 298, in _wrapper
    method(*method_args)
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 546, in timer_setup
    future = self.qtile.run_in_executor(self.poll)
  File "/home/tcl/Software/qtile/libqtile/core/manager.py", line 913, in run_in_executor
    return self._eventloop.run_in_executor(None, func, *args)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 807, in run_in_executor
    self._check_default_executor()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 514, in _check_default_executor
    raise RuntimeError('Executor shutdown has been called')
RuntimeError: Executor shutdown has been called
2021-02-25 22:28:05,017 ERROR libqtile base.py:on_done():L542 Failed to reschedule.
Traceback (most recent call last):
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 534, in on_done
    self.update(result)
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 550, in update
    old_width = self.layout.width
  File "/home/tcl/Software/qtile/libqtile/drawer.py", line 80, in width
    return self.layout.get_pixel_size()[0]
  File "/home/tcl/Software/qtile/libqtile/pangocffi.py", line 132, in get_pixel_size
    pango.pango_layout_get_pixel_size(self._pointer, width, height)
TypeError: initializer for ctype 'PangoLayout *' must be a cdata pointer, not NoneType
2021-02-25 22:28:05,017 ERROR libqtile base.py:_wrapper():L300 got exception from widget timer
Traceback (most recent call last):
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 298, in _wrapper
    method(*method_args)
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 463, in timer_setup
    update_interval = self.tick()
  File "/home/tcl/Software/qtile/libqtile/widget/clock.py", line 73, in tick
    self.update(self.poll())
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 493, in update
    old_width = self.layout.width
  File "/home/tcl/Software/qtile/libqtile/drawer.py", line 80, in width
    return self.layout.get_pixel_size()[0]
  File "/home/tcl/Software/qtile/libqtile/pangocffi.py", line 132, in get_pixel_size
    pango.pango_layout_get_pixel_size(self._pointer, width, height)
TypeError: initializer for ctype 'PangoLayout *' must be a cdata pointer, not NoneType
2021-02-25 22:28:05,019 WARNING libqtile lifecycle.py:_atexit():L34 Restarting Qtile with os.execv(...)
2021-02-25 22:28:06,001 ERROR libqtile base.py:on_done():L530 poll() raised exceptions, not rescheduling
Traceback (most recent call last):
  File "/usr/lib/python3.9/urllib/request.py", line 1342, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.9/http/client.py", line 1255, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1301, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1250, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1010, in _send_output
    self.send(msg)
  File "/usr/lib/python3.9/http/client.py", line 950, in send
    self.connect()
  File "/usr/lib/python3.9/http/client.py", line 921, in connect
    self.sock = self._create_connection(
  File "/usr/lib/python3.9/socket.py", line 822, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/usr/lib/python3.9/socket.py", line 953, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/tcl/Software/qtile/libqtile/widget/base.py", line 527, in on_done
    result = future.result()
  File "/usr/lib/python3.9/concurrent/futures/thread.py", line 52, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/tcl/Software/qtile/libqtile/widget/generic_poll_text.py", line 85, in poll
    body = self.fetch(self.url, data, headers, self.json, self.xml)
  File "/home/tcl/Software/qtile/libqtile/widget/generic_poll_text.py", line 58, in fetch
    res = urlopen(req)
  File "/usr/lib/python3.9/urllib/request.py", line 214, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.9/urllib/request.py", line 517, in open
    response = self._open(req, data)
  File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.9/urllib/request.py", line 1371, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "/usr/lib/python3.9/urllib/request.py", line 1345, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>
2021-02-25 22:28:06,003 WARNING libqtile base.py:on_done():L544 poll() returned None, not rescheduling
```

Maybe somebody could try to confirm this? (As long as you are using systemd it should be very easy.)


Discussion:

Resolving patch:
diff --git a/libqtile/core/manager.py b/libqtile/core/manager.py
--- a/libqtile/core/manager.py
+++ b/libqtile/core/manager.py
@@ -236,7 +236,7 @@ async def async_loop(self) -> None:
             async with LoopContext({
                 signal.SIGTERM: self.stop,
                 signal.SIGINT: self.stop,
-                signal.SIGHUP: self.restart,
+                signal.SIGHUP: self.stop,
             }), ipc.Server(
                 self._prepare_socket_path(self.socket_path),
                 self.server.call,


Test patch: