Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sometimes hhpc is so much hungry that it eats my pointer #9

Open
LemonBoy opened this issue Dec 19, 2014 · 9 comments
Open

Sometimes hhpc is so much hungry that it eats my pointer #9

LemonBoy opened this issue Dec 19, 2014 · 9 comments

Comments

@LemonBoy
Copy link

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

@aktau
Copy link
Owner

aktau commented Dec 19, 2014

That's definitely not good at all. Could you run hhpc verbosely with the -v switch and see what it prints out?

@LemonBoy
Copy link
Author

I've finally managed to catch it 🎯

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

@Earnestly
Copy link

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.

@Earnestly
Copy link

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.

@Earnestly
Copy link

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);
     }
 }

@Earnestly
Copy link

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.

@Earnestly
Copy link

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

@Earnestly
Copy link

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

@rudyon
Copy link

rudyon commented Jun 4, 2023

can confirm this happens for me too. i am currently working around it manually by running killall hhpc; hhpc & disown in a terminal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants