100% cpu after Xorg exits
I run a single user system and I frequently start and exit X through xrdp. The start of aw-watcher-window is part of my wm launching configuration (.i3/config in my case). When Xorg exits aw-watcher-window goes to 100% cpu usage. I've written https://gist.github.com/phromo/6a41be2bc4d716751eee2eb29856d4bb as a workaround, but that's not the proper way to do it :)
This is primarily an issue with your startup method rather than a activitywatch.
In unix/linux if a process dies it kills all of its children, so if you start aw-watcher-window straight from a terminal window (without tmux or something like that) it will close when you close the window, the same thing goes for your windowmanager. Personally at home I run bspwm and have aw-server running as a systemd service while I start aw-watcher-{window,afk} in my .xinitrc which works fine even after I restart the wm. I run i3 at my work computer where i simply exec aw-qt in my .i3/config aswell, but have not tested to restart it without restarting my whole computer, will try that when I have the time.
However, even if aw-watcher-window fails to communicate with the Xorg server it should still not use 100% CPU. Not sure what is causing that, maybe take a look at the log and stdout?
Well that's an interesting bug. From a quick glance I'm not sure what takes up all the CPU but if you could provide the output of python3 -m cProfile --sort=cumtime aw_watcher_window/__main__.py after having it peak CPU for a while then that'd be really helpful!
Launching:
⋊>phromo@thingybox ~/p/a/a/aw-watcher-window on eb0f791 env DISPLAY=:10 python -m cProfile --sort=cumtime ~/program/activivity-watch/activitywatch/aw-watcher-window/aw_watcher_window/__main__.py
2018-05-14 19:45:24 [INFO ]: Running watcher with poll time 1.0 seconds (aw_watcher_window.main:35)
2018-05-14 19:45:24 [INFO ]: aw-watcher-window has started (aw_watcher_window.main:44)
2018-05-14 19:45:24 [INFO ]: Connection to aw-server established by aw-watcher-window (aw_client.client:298)
Shutting down Xorg:
2018-05-14 19:45:33 [ERROR]: Exception thrown while trying to get active window: 'BrokenPipeError' object is not subscriptable (aw_watcher_window.main:69)
Traceback (most recent call last):
File "/home/phromo/Apps/anaconda3/lib/python3.6/site-packages/python_xlib-0.23-py3.6.egg/Xlib/protocol/display.py", line 584, in send_and_recv
i = self.socket.send(self.data_send)
BrokenPipeError: [Errno 32] Broken pipe
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/phromo/program/activivity-watch/activitywatch/aw-watcher-window/aw_watcher_window/main.py", line 66, in heartbeat_loop
current_window = get_current_window()
File "/home/phromo/program/activivity-watch/activitywatch/aw-watcher-window/aw_watcher_window/lib.py", line 44, in get_current_window
return get_current_window_linux()
File "/home/phromo/program/activivity-watch/activitywatch/aw-watcher-window/aw_watcher_window/lib.py", line 7, in get_current_window_linux
window = xlib.get_current_window()
File "/home/phromo/program/activivity-watch/activitywatch/aw-watcher-window/aw_watcher_window/xlib.py", line 37, in get_current_window
window_id = _get_current_window_id()
File "/home/phromo/program/activivity-watch/activitywatch/aw-watcher-window/aw_watcher_window/xlib.py", line 20, in _get_current_window_id
window_prop = screen.root.get_full_property(atom, X.AnyPropertyType)
File "/home/phromo/Apps/anaconda3/lib/python3.6/site-packages/python_xlib-0.23-py3.6.egg/Xlib/xobject/drawable.py", line 472, in get_full_property
prop = self.get_property(property, property_type, 0, sizehint)
File "/home/phromo/Apps/anaconda3/lib/python3.6/site-packages/python_xlib-0.23-py3.6.egg/Xlib/xobject/drawable.py", line 461, in get_property
long_length = length)
File "/home/phromo/Apps/anaconda3/lib/python3.6/site-packages/python_xlib-0.23-py3.6.egg/Xlib/protocol/rq.py", line 1369, in __init__
self.reply()
File "/home/phromo/Apps/anaconda3/lib/python3.6/site-packages/python_xlib-0.23-py3.6.egg/Xlib/protocol/rq.py", line 1381, in reply
self._display.send_and_recv(request = self._serial)
File "/home/phromo/Apps/anaconda3/lib/python3.6/site-packages/python_xlib-0.23-py3.6.egg/Xlib/protocol/display.py", line 586, in send_and_recv
self.close_internal('server: %s' % err[1])
TypeError: 'BrokenPipeError' object is not subscriptable
Hitting Ctrl-C after awhile of 100% cpu:
^C 326156379 function calls (326150472 primitive calls) in 75.018 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
341/1 0.006 0.000 75.019 75.019 {built-in method builtins.exec}
1 0.000 0.000 75.019 75.019 __main__.py:1(<module>)
1 0.000 0.000 74.881 74.881 main.py:20(main)
1 0.000 0.000 74.878 74.878 main.py:59(heartbeat_loop)
11 0.000 0.000 64.834 5.894 lib.py:42(get_current_window)
11 0.000 0.000 64.834 5.894 lib.py:5(get_current_window_linux)
26 0.000 0.000 64.813 2.493 rq.py:1358(__init__)
11 0.000 0.000 64.813 5.892 xlib.py:36(get_current_window)
11 0.000 0.000 64.813 5.892 xlib.py:18(_get_current_window_id)
11 0.000 0.000 64.812 5.892 drawable.py:471(get_full_property)
11 0.000 0.000 64.812 5.892 drawable.py:454(get_property)
26 33.512 1.289 64.811 2.493 rq.py:1371(reply)
46562181 22.061 0.000 26.623 0.000 display.py:388(send_and_recv)
10 10.009 1.001 10.009 1.001 {built-in method time.sleep}
279373433 9.234 0.000 9.234 0.000 lock.py:36(__noop)
16 0.000 0.000 0.280 0.018 __init__.py:1(<module>)
360/2 0.001 0.000 0.159 0.080 <frozen importlib._bootstrap>:966(_find_and_load)
358/2 0.001 0.000 0.159 0.080 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
457/2 0.000 0.000 0.159 0.079 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
350/2 0.001 0.000 0.159 0.079 <frozen importlib._bootstrap>:651(_load_unlocked)
310/2 0.001 0.000 0.159 0.079 <frozen importlib._bootstrap_external>:672(exec_module)
1 0.000 0.000 0.130 0.130 main.py:1(<module>)
107/18 0.000 0.000 0.123 0.007 {built-in method builtins.__import__}
1009/446 0.001 0.000 0.111 0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
8/1 0.000 0.000 0.109 0.109 <frozen importlib._bootstrap>:622(_load_backward_compatible)
3/1 0.001 0.000 0.109 0.109 {method 'load_module' of 'zipimport.zipimporter' objects}
1 0.000 0.000 0.106 0.106 client.py:1(<module>)
1 0.000 0.000 0.099 0.099 __init__.py:41(<module>)
1 0.000 0.000 0.043 0.043 pyopenssl.py:43(<module>)
11 0.000 0.000 0.038 0.003 __init__.py:5(<module>)
2 0.000 0.000 0.033 0.016 __init__.py:3(<module>)
1400/1398 0.013 0.000 0.031 0.000 {built-in method builtins.__build_class__}
1 0.000 0.000 0.030 0.030 connectionpool.py:1(<module>)
353/322 0.001 0.000 0.029 0.000 <frozen importlib._bootstrap>:870(_find_spec)
10 0.000 0.000 0.029 0.003 client.py:152(heartbeat)
in a manner similar to @johan-bjareholt I moved the initialization of aw-watcher-* to .xsession. That makes the processes terminate upon Xorg exit (I don't understand why i3 exec is designed not to have this property)
https://github.com/python-xlib/python-xlib/blob/master/Xlib/protocol/display.py#L427
This is likely the cause, don't have time to dig through the Xlib code now but might later.
Should be fixed according to https://github.com/ActivityWatch/activitywatch/issues/920#issuecomment-1768076756