bakkeby / dwm-flexipatch

A dwm build with preprocessor directives to decide which patches to include during build time
MIT License
1.15k stars 232 forks source link

When using dwm-msg run_command viewtoleft/right in a script, last tags window still visible until mouse moves #433

Closed fov95 closed 1 month ago

fov95 commented 1 month ago

I wanted to use this script to get a hotcorner-esque function for my mouse scroll wheel:

# get mouse position, window id and screen
 eval "$(xdotool getmouselocation --shell)"

up(){
  if [ "$X" = 0 ] && [ "$Y" = 0 ]; then
    dwm-msg run_command rotatestack 0; dwm-msg run_command focusstack 1
  else
    dwm-msg run_command viewtoleft
  fi
}

down(){
  if [ "$X" = 0 ] && [ "$Y" = 0 ]; then
    dwm-msg run_command rotatestack 1; dwm-msg run_command focusstack 0
  else
    dwm-msg run_command viewtoright
  fi
}

case "$1" in
  up)   up  ;;
  down) down ;;
esac

It work's but if the last tag has a window on it, it is still visible on the next empty tag until I move my mouse again. Any idea why this might happen? It also happens when I run the command in a terminal. It doesn't happen if I just run dwm-msg run_command viewtoright/left in terminal.

bakkeby commented 1 month ago

I am not entirely sure as I can't reproduce this behaviour.

Can you give me the list of patches that you have enabled (in case it is a patch compatibility issue).

Maybe try this without a compositor as that can sometimes interfere.

fov95 commented 1 month ago

Same without compositor

/* Bar functionality */
#include "bar_indicators.h"
#include "bar_tagicons.h"

#include "bar_ewmhtags.h"

/* Other patches */
#include "cfacts.h"
#include "cool_autostart.h"
#include "cyclelayouts.h"
#include "dragcfact.h"
#include "dragmfact.h"
#include "fakefullscreenclient.h"
#include "focusdir.h"
#include "focusadjacenttag.h"
#include "fullscreen.h"
#include "ipc.h"
#include "ipc/ipc.h"
#include "ipc/util.h"
#include "insets.h"
#include "moveresize.h"
#include "movestack.h"
#include "nomodbuttons.h"
#include "pertag.h"
#include "placemouse.h"
#include "restartsig.h"
#include "rotatestack.h"
#include "setborderpx.h"
#include "shiftview.h"
#include "shiftviewclients.h"
#include "sticky.h"
#include "swallow.h"
#include "togglefullscreen.h"
#include "unfloatvisible.h"
#include "vanitygaps.h"
#include "zoomswap.h"
#include "xrdb.h"
/* Layouts */
#include "layout_flextile-deluxe.h"
fov95 commented 1 month ago

Well guess I am not going to use that script at all. If I scroll too fast dwm crashes and xdo gives error that it couldn't create a new xdo instance or so..

bakkeby commented 1 month ago

If dwm crashes then it sounds like a bug.

Considering that you provided the include statements from patch/include.h rather than patches.h I take it that you have finalized the build using the flexipatch-finalizer script. Also notable is the missing #include "bar.h" which was added more than two years ago, suggesting that your build may be fairly old.

https://github.com/bakkeby/dwm-flexipatch/blob/f4258747be3215c75fbb57cc4169da6b50b02726/patch/include.h#L1-L6

I tried with builds going back as far as 3 years ago when the IPC patch was added, but I wasn't able to reproduce the issue (I am doing this via Xephyr).

xdo gives error that it couldn't create a new xdo instance

That sounds like the X server may be running out of available display connections.

I remember there were some cases with st where it would leak display connections when reloading resources due to a missing XCloseDisplay call when reloading the config, and this would cause "Maximum amount of clients reached" errors preventing new windows from opening [ref].

It may be worth checking the number of display connections used by running programs, e.g.

lsof | awk '/libX11.so/ {clients[$1]++;} END {for(c in clients){printf "%s\t%s\n", clients[c], c;}}'

The following command should be quicker, but it doesn't work for me.

lsof +c0 /usr/lib/libX11.so | cut -d' ' -f1

Both commands are from https://bbs.archlinux.org/viewtopic.php?id=188052

fov95 commented 1 month ago

Yea I did finalize. Contrary to your recommendation I am using dwm-flexipatch as my main build because I am too stupid for C. Yea my build is pretty old but I made some manual changes which I forgot and creating a new build means I have to figure this stuff out again at some point.. xD Firefox has 132, chromium 177 and 'Isolated' has 660.. This after a fresh start with only 3-4 apps open.. xD So.. I am really thankful for your effort.. I don't really know what to do with that info now..

I also tried it in xephyr and I get the same results. Only thing running in the xephyr instance is a terminal window to check if it stays when scrolling. It also crashes when I am too fast:

Received EPOLLIN event on socket
{"result":"success"}
Got event from unknown fd 6, ptr 0x6, u32 6, u64 6 with events 17
Failed to close epoll file descriptor
[2]  + 25997 done       .config/suckless/dwm-xephyr/dwm
Error receiving response from socket. The connection might have been lost.
Error receiving response from socket. The connection might have been lost.

and the last window stays on screen when switching to new tag until I move my mouse again.. I suppose there is an issue with my build then xD Should I close? xD

bakkeby commented 1 month ago

If you share your build somehow then I may be able to replicate and advice on how to fix it.

fov95 commented 1 month ago

aight :) https://github.com/fov95/dwm

bakkeby commented 1 month ago
diff --git a/patch/ipc/ipc.c b/patch/ipc/ipc.c
index eae9667..3f57c6b 100644
--- a/patch/ipc/ipc.c
+++ b/patch/ipc/ipc.c
@@ -1170,6 +1170,7 @@ ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
     else if (msg_type == IPC_TYPE_RUN_COMMAND) {
       if (ipc_run_command(c, msg) < 0) return -1;
       ipc_send_events(mons, lastselmon, selmon);
+      XSync(dpy, False);
     } else if (msg_type == IPC_TYPE_GET_DWM_CLIENT) {
       if (ipc_get_dwm_client(c, msg, mons) < 0) return -1;
     } else if (msg_type == IPC_TYPE_SUBSCRIBE) {

This is a quite peculiar issue.

In your setup you have no bar (as in you are using an external bar like polybar or lemonbar as an example).

We are using the dwm-msg command as a "remote control" of sorts, which makes the viewtoright function execute resulting in XMoveWindow calls (via showhide) that are essentially queuing messages that are going to be sent to the X server.

The problem is that there is nothing that triggers these messages to be synchronized with the server, as in making sure that the messages are sent to the server and that the server has processed them.

Normally this is triggered by other things like the bar being drawn or mouse or keyboard events being received by the window manager.

Forcing a synchronization after the command has been executed seems to address this issue in your build. Alternatively you could put this at the end of the viewtoright and viewtoleft functions, but adding it at the end of the IPC command execution kind of made more sense.

I was not able to reproduce dwm crashing in relation to this, but let me know if you find a way to reproduce that consistently (using Xephyr presumably).

fov95 commented 1 month ago

Thank you very much. :) That did the trick for the window staying on new tag. Thanks for the explanation.

The crashing is consistent for me with and without compositor, also on fresh start, also on xephyr.. If I scroll too fast (with the script enables ofc) dwm just dies.. Last error I got in TTY: Exiting due to channel error. [GFX1-]: CompositorBridgeChild receives IPS close with reason=AbnormalShutdown dwm doesn't die with the normal functions, only with that script in place. The 2 error messages I gave is all I have unless you can tell me an other place where to look for a log or something.. edit: I'll try to get something out of xephyr edit2: Xephyr doesn't give any other output than the provided..

bakkeby commented 1 month ago

Can you show me the command you set up to use that script as a hotcorner area?

I tried something like this

xdotool behave_screen_edge top-left exec ~/tmp/dwmf_433/hotcorner.sh down

but you would have something that reacts to the mouse scroll wheel.

fov95 commented 1 month ago

The script from start post is called here:

{ ClkRootWin,           0,                  Button4,        spawn,    SHCMD("dwm_view_direction up") },
{ ClkRootWin,           0,                  Button5,        spawn,    SHCMD("dwm_view_direction down") },

I always have gaps on so that I have access to root window. with xdotool getmouselocation I think I have better control, I can use math to have as many spots/regions as I want.

bakkeby commented 1 month ago

Oh I see. Well, the good news is that I can reproduce this crash both with your build and with latest dwm-flexipatch. But I can't reproduce this with my own build.

I'll need to experiment a bit more.

bakkeby commented 1 month ago

Alright.

I am not going to pretend to understand this, but when you scroll too fast it seems that epoll events may be stacking up and then we see output like this just before it "crashes":

Got event from unknown fd 7, ptr 0x7, u32 7, u64 7 with events 17

More specifically it hits the return in the else section of this block of the run function, which simply means that dwm stops running when this happens.

https://github.com/bakkeby/dwm-flexipatch/blob/f4258747be3215c75fbb57cc4169da6b50b02726/dwm.c#L3300-L3317

If you remove the return; statement then this issue should go away with no apparent consequences.


Further analysis:

If I enable debug logging for the IPC patch I get this for one scroll.

spawn cmd /home/sbakkeby/tmp/dwmf_433/hotcorner.sh
Got event from fd 6
Received EPOLLIN event on socket
Adding client with fd 7 to list
New client at fd: 7
Got event from fd 7
Received message from fd 7
[fd 7] Received message: '{"command":"viewtoright","args":[]}' Message type: 0 Message size: 36
Received command: viewtoright
Called function for command viewtoright
Got event from fd 7
Sending message to client at fd 7...
Wrote 33/33 to client at fd 7
{"result":"success"}
Got event from fd 7
EPOLLHUP received from client at fd 7
Successfully removed client on fd 7

If I scroll too fast I get.

spawn cmd /home/sbakkeby/tmp/dwmf_433/hotcorner.sh
Got event from fd 6
Received EPOLLIN event on socket
Adding client with fd 7 to list
New client at fd: 7
Got event from fd 7
Received message from fd 7
[fd 7] Received message: '{"command":"viewtoright","args":[]}' Message type: 0 Message size: 36
Received command: viewtoright
Called function for command viewtoright
Got event from fd 7
Sending message to client at fd 7...
Wrote 33/33 to client at fd 7
{"result":"success"}
Got event from fd 3
spawn cmd /home/sbakkeby/tmp/dwmf_433/hotcorner.sh
Got event from fd 7
EPOLLHUP received from client at fd 7
Successfully removed client on fd 7
Got event from fd 7
Got event from unknown fd 7, ptr 0x7, u32 7, u64 7 with events 17
spawn cmd /home/sbakkeby/tmp/dwmf_433/hotcorner.sh
Failed to close epoll file descriptor

So it seems that a race condition occurs between a file descriptor from a dwm-msg command that is exiting vs a new message coming in that happens to end up with the same file descriptor.

fov95 commented 1 month ago

Good analysis.. I'm also not pretending to understand any of this, but it kinda makes sense.. Is it safe to remove that return tho? You probably mean no foreseeable consequence? :D Not that I have any clue whatsoever :D Yet again you fixed a problem that wasn't even really related to your project. Thank you very much. Will make a small donation.

bakkeby commented 1 month ago

I think there is no real risk removing that return statement, I haven't had any issues with that so far (happen to have removed that in my own build a long time ago). I suppose one could try scrolling for a few hours to see if something breaks :)