hhpc
hhpc copied to clipboard
Sometimes hhpc is so much hungry that it eats my pointer
I couldn't find anything about the nutritional values of a pointer but I guess it's not much healthy for hhpc. It just happens randomly, I can get it back after killing hhpc :(
That's definitely not good at all. Could you run hhpc verbosely with the -v
switch and see what it prints out?
I've finally managed to catch it :dart:
hhpc: draining event
hhpc: succesfully grabbed mouse pointer
hhpc: event received, ungrabbing and sleeping
hhpc: draining event
hhpc: succesfully grabbed mouse pointer
hhpc: event received, ungrabbing and sleeping
hhpc: draining event
hhpc: succesfully grabbed mouse pointer
hhpc: event received, ungrabbing and sleeping
hhpc: draining event
hhpc: succesfully grabbed mouse pointer
hhpc: event received, ungrabbing and sleeping
hhpc: draining event
hhpc: XGrabPointer: already grabbed mouse pointer, retrying with delay
hhpc: XGrabPointer: already grabbed mouse pointer, retrying with delay
hhpc: XGrabPointer: already grabbed mouse pointer, retrying with delay
hhpc: XGrabPointer: already grabbed mouse pointer, retrying with delay
hhpc: XGrabPointer: already grabbed mouse pointer, retrying with delay
hhpc: XGrabPointer: already grabbed mouse pointer, retrying with delay
hhpc: succesfully grabbed mouse pointer
This seems related to the nanosleep()
returning earlier (EINTR) in the
delay()
function.
If nanosleep is interupted it will return early with a return value of -1
.
Since you don't use rmtp
(NULL
) nanosleep won't return the time remaining.
From there you set the global state of working
to 0
and the main while loop
here:
while (working && grabPointer(dpy, win, emptyCursor, mask)) {
always fails.
This is speculation though, I have experienced this as well but didn't think to fire up perf or gdb to investigate.
As a follow up, I can manually set working
to 0
in gdb and replicate this
behaviour. The program never recovers from this and the cursor stays hidden
indefinately.
Here is an untested potential fix for this, it basically just continues after
being interupted. It does not handle EINVAL
. It may be better to just crash
instead of setting working
to 0
though.
[Edit: I could make this a Pull Request if you wish.]
diff --git a/hhpc.c b/hhpc.c
index f106f7f..54e5dc8 100644
--- a/hhpc.c
+++ b/hhpc.c
@@ -38,6 +38,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
static int gIdleTimeout = 1;
static int gVerbose = 0;
@@ -90,8 +91,11 @@ static void delay(time_t sec, long msec) {
sleep.tv_sec = sec;
sleep.tv_nsec = (msec % 1000) * 1000 * 1000;
- if (nanosleep(&sleep, NULL) == -1) {
- signalHandler(0);
+ while (nanosleep(&sleep, &sleep) != 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ signalHandler(0);
}
}
Hm, this may not be the cause as I suspected, although it does fix one error case.
It seems to get stuck in select()
sometimes and never returns.
This might be a CANTFIX
issue. Either way here's some gdb output after
catching it fail:
Attaching to process 26362
Reading symbols from /usr/bin/hhpc...done.
Reading symbols from /usr/lib/libX11.so.6...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libc.so.6...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libxcb.so.1...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libdl.so.2...(no debugging symbols found)...done.
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libXau.so.6...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libXdmcp.so.6...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libXcursor.so.1...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libXrender.so.1...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libXfixes.so.3...(no debugging symbols found)...done.
0x00007fc2b2c69ae3 in __select_nocancel () from /usr/lib/libc.so.6
(gdb) l
warning: Source file is more recent than executable.
234 switch (option) {
235 case 'i': gIdleTimeout = atoi(optarg); break;
236 case 'v': gVerbose = 1; break;
237 default: return 0;
238 }
239 }
240
241 return 1;
242 }
243
(gdb) p working
$1 = 1
(gdb) bt
#0 0x00007fc2b2c69ae3 in __select_nocancel () from /usr/lib/libc.so.6
#1 0x000000000040135a in waitForMotion (dpy=dpy@entry=0xdd6010, win=win@entry=197, timeout=1) at hhpc.c:200
#2 0x00000000004014a3 in main (argc=<optimized out>, argv=<optimized out>) at hhpc.c:274
(gdb) bt full
#0 0x00007fc2b2c69ae3 in __select_nocancel () from /usr/lib/libc.so.6
No symbol table info available.
#1 0x000000000040135a in waitForMotion (dpy=dpy@entry=0xdd6010, win=win@entry=197, timeout=1) at hhpc.c:200
ready = <optimized out>
xfd = 3
fds = {__fds_bits = {8, 0 <repeats 15 times>}}
event = {type = 6, xany = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, window = 197}, xkey = {type = 6, serial = 6368, send_event = 0,
display = 0xdd6010, window = 197, root = 197, subwindow = 6294090, time = 242038321, x = 504, y = 1041, x_root = 504, y_root = 1041, state = 0, keycode = 0,
same_screen = 1}, xbutton = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, window = 197, root = 197, subwindow = 6294090, time = 242038321,
x = 504, y = 1041, x_root = 504, y_root = 1041, state = 0, button = 0, same_screen = 1}, xmotion = {type = 6, serial = 6368, send_event = 0,
display = 0xdd6010, window = 197, root = 197, subwindow = 6294090, time = 242038321, x = 504, y = 1041, x_root = 504, y_root = 1041, state = 0,
is_hint = 0 '\000', same_screen = 1}, xcrossing = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, window = 197, root = 197,
subwindow = 6294090, time = 242038321, x = 504, y = 1041, x_root = 504, y_root = 1041, mode = 0, detail = 0, same_screen = 1, focus = 32706, state = 465},
xfocus = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, window = 197, mode = 197, detail = 0}, xexpose = {type = 6, serial = 6368,
send_event = 0, display = 0xdd6010, window = 197, x = 197, y = 0, width = 6294090, height = 0, count = 242038321}, xgraphicsexpose = {type = 6,
serial = 6368, send_event = 0, display = 0xdd6010, drawable = 197, x = 197, y = 0, width = 6294090, height = 0, count = 242038321, major_code = 0,
minor_code = 504}, xnoexpose = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, drawable = 197, major_code = 197, minor_code = 0},
xvisibility = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, window = 197, state = 197}, xcreatewindow = {type = 6, serial = 6368,
send_event = 0, display = 0xdd6010, parent = 197, window = 197, x = 6294090, y = 0, width = 242038321, height = 0, border_width = 504,
override_redirect = 1041}, xdestroywindow = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, event = 197, window = 197}, xunmap = {type = 6,
serial = 6368, send_event = 0, display = 0xdd6010, event = 197, window = 197, from_configure = 6294090}, xmap = {type = 6, serial = 6368, send_event = 0,
display = 0xdd6010, event = 197, window = 197, override_redirect = 6294090}, xmaprequest = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010,
parent = 197, window = 197}, xreparent = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, event = 197, window = 197, parent = 6294090,
x = 242038321, y = 0, override_redirect = 504}, xconfigure = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, event = 197, window = 197,
x = 6294090, y = 0, width = 242038321, height = 0, border_width = 504, above = 4471060955640, override_redirect = 0}, xgravity = {type = 6, serial = 6368,
send_event = 0, display = 0xdd6010, event = 197, window = 197, x = 6294090, y = 0}, xresizerequest = {type = 6, serial = 6368, send_event = 0,
display = 0xdd6010, window = 197, width = 197, height = 0}, xconfigurerequest = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, parent = 197,
window = 197, x = 6294090, y = 0, width = 242038321, height = 0, border_width = 504, above = 4471060955640, detail = 0, value_mask = 140471200382977},
xcirculate = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, event = 197, window = 197, place = 6294090}, xcirculaterequest = {type = 6,
serial = 6368, send_event = 0, display = 0xdd6010, parent = 197, window = 197, place = 6294090}, xproperty = {type = 6, serial = 6368, send_event = 0,
display = 0xdd6010, window = 197, atom = 197, time = 6294090, state = 242038321}, xselectionclear = {type = 6, serial = 6368, send_event = 0,
display = 0xdd6010, window = 197, selection = 197, time = 6294090}, xselectionrequest = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010,
owner = 197, requestor = 197, selection = 6294090, target = 242038321, property = 4471060955640, time = 4471060955640}, xselection = {type = 6,
serial = 6368, send_event = 0, display = 0xdd6010, requestor = 197, selection = 197, target = 6294090, property = 242038321, time = 4471060955640},
xcolormap = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, window = 197, colormap = 197, new = 6294090, state = 0}, xclient = {type = 6,
serial = 6368, send_event = 0, display = 0xdd6010, window = 197, message_type = 197, format = 6294090, data = {
b = "16m\016\000\000\000\000\370\001\000\000\021\004\000\000\370\001\000", s = {13873, 3693, 0, 0, 504, 0, 1041, 0, 504, 0}, l = {242038321,
4471060955640, 4471060955640, 0, 140471200382977}}}, xmapping = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010, window = 197,
request = 197, first_keycode = 0, count = 6294090}, xerror = {type = 6, display = 0x18e0, resourceid = 17732945007607808, serial = 14508048,
error_code = 197 '\305', request_code = 0 '\000', minor_code = 0 '\000'}, xkeymap = {type = 6, serial = 6368, send_event = 0, display = 0xdd6010,
window = 197, key_vector = "\305\000\000\000\000\000\000\000J\n`\000\000\000\000\000\061\066m\016\000\000\000\000\370\001\000\000\021\004\000"}, xgeneric = {
type = 6, serial = 6368, send_event = 0, display = 0xdd6010, extension = 197, evtype = 0}, xcookie = {type = 6, serial = 6368, send_event = 0,
display = 0xdd6010, extension = 197, evtype = 0, cookie = 197, data = 0x600a4a}, pad = {140471200382982, 6368, 17732945007607808, 14508048, 197, 197,
6294090, 242038321, 4471060955640, 4471060955640, 0, 140471200382977, 465, 140474202610552, 140474202610552, 35188667056187, 287948944191717396,
844553846194176, 257698037760, 140474202604096, 401, 140474202610552, 140474202610552, 287948944191717376}}
emptyCursor = 4194307
#2 0x00000000004014a3 in main (argc=<optimized out>, argv=<optimized out>) at hhpc.c:274
displayName = <optimized out>
dpy = 0xdd6010
scr = <optimized out>
rootwin = 197
Okay, well I seem to have "fixed" this by simply adding a timeout on the
select()
. This is not really very satisfactory.
diff --git a/hhpc.c b/hhpc.c
index f106f7f..84f6cc0 100644
--- a/hhpc.c
+++ b/hhpc.c
@@ -193,7 +193,15 @@ static void waitForMotion(Display *dpy, Window win, int timeout) {
* is interruptible by signals, which allows ctrl+c to work. If we
* were to just use XNextEvent() (which blocks), ctrl+c would not
* work. */
- ready = select(xfd + 1, &fds, NULL, NULL, NULL);
+ struct timeval tv = {5, 0}; /* waits 5 seconds */
+
+ if ((ready = select(xfd + 1, &fds, NULL, NULL, &tv)) == -1) {
+ if (working) perror("hhpc: error while select()'ing");
+ }
+
+ if (ready == 0) {
+ if (gVerbose) fprintf(stderr, "hhpc: timeout\n");
+ }
if (ready > 0) {
if (gVerbose) fprintf(stderr, "hhpc: event received, ungrabbing and sleeping\n");
@@ -211,12 +219,6 @@ static void waitForMotion(Display *dpy, Window win, int timeout) {
delay(timeout, 0);
}
- else if (ready == 0) {
- if (gVerbose) fprintf(stderr, "hhpc: timeout\n");
- }
- else {
- if (working) perror("hhpc: error while select()'ing");
- }
}
XUngrabPointer(dpy, CurrentTime);
I placed a 5 second timeout and this is the result after experiencing a lockout:
hhpc: succesfully grabbed mouse pointer
hhpc: event received, ungrabbing and sleeping
hhpc: draining event
hhpc: draining event
hhpc: draining event
[ ... ] About 100 of these events
hhpc: draining event
hhpc: draining event
hhpc: draining event
hhpc: succesfully grabbed mouse pointer
hhpc: event received, ungrabbing and sleeping
can confirm this happens for me too. i am currently working around it manually by running killall hhpc; hhpc & disown
in a terminal