aw-watcher-window icon indicating copy to clipboard operation
aw-watcher-window copied to clipboard

100% cpu after Xorg exits

Open phromo opened this issue 7 years ago • 5 comments

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 :)

phromo avatar May 14 '18 10:05 phromo

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?

johan-bjareholt avatar May 14 '18 11:05 johan-bjareholt

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!

ErikBjare avatar May 14 '18 12:05 ErikBjare

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)

phromo avatar May 14 '18 17:05 phromo

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)

phromo avatar May 14 '18 17:05 phromo

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.

johan-bjareholt avatar May 14 '18 18:05 johan-bjareholt

Should be fixed according to https://github.com/ActivityWatch/activitywatch/issues/920#issuecomment-1768076756

ErikBjare avatar Jun 04 '24 12:06 ErikBjare