-
Notifications
You must be signed in to change notification settings - Fork 39
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
Rootless mode: Qt applications do not exit #1065
Comments
You probably will need to look at Qt code. It looks like the second thread is an X11 event loop, which isn't weird at all. It also doesn't mean that it's actually waiting for a specific event (I guess?), it's just part of the normal X11 event handling. Now, obviously, this thread should terminate once you try to quit an application, but why that is not happening beats me without looking at Qt code. |
Thank you for this first (and extremely fast) feedback :) |
Looking around, it seems that quite some people have had issues with newer Qt versions and more exotic X servers (mostly on Windows, like XMing), which lead to the application window not showing up at all. They also got a BadRequest with codes {130,47}, but that might be a red herring. The major code should be related to the MIT-SHM/XShm extension, minor code 47 is... I don't know. X_ShmPutImage should be 3, which is usually failing, I'm having a hard time finding out what 47 is supposed to be. It's probably something that we don't provide in NX, so it makes sense that Qt gets a BadRequest. But if you don't see this message right when quitting applications, but rather right at the start, it probably means that it has nothing todo with the quitting issue. |
Weird stuff indeed. There is no minor opcode 47 in https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/blob/master/include/X11/extensions/shmproto.h?ref_type=heads , which makes the BadRequest response very understandable... now... what did Qt try to call exactly? The XInput2 extension does have a minor opcode of 47, which would be XIQueryVersion: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/blob/master/include/X11/extensions/XI2proto.h?ref_type=heads#L82 I think we're not providing XInput2 at all in NX. The combination used here doesn't make sense, though... |
Yes, most likely.
I mentioned these warnings for the sake of completeness but, indeed, I should have mentioned they appear right at the start. I am going to adjust my report accordingly.
Confirmed, I remember having checked that point. |
Unfortunately I am having no working environment ATM where I could test. So
my first suggested is to retry with some extensions disabled. Please check
-extension and -noshm and the like in nxagent manage.
Nevertheless for me it looks like a bug in qt appearing in a code path that
is not run on "normal" X servers providing all current extensions.
Uli
Xavier G. ***@***.***> schrieb am So., 10. Sept. 2023, 07:53:
… that might be a red herring.
Yes, most likely.
But if you don't see this message right when quitting applications, but
rather right at the start, it probably means that it has nothing todo with
the quitting issue.
I mentioned these warnings for the sake of completeness but, indeed, I
should have mentioned they appear right at the start. I am going to adjust
my report accordingly.
I think we're not providing XInput2 at all in NX.
Confirmed, I remember having checked that point.
—
Reply to this email directly, view it on GitHub
<#1065 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABQHBZEA3TZIXOTJH4ER7O3XZVIXDANCNFSM6AAAAAA4R4ADGQ>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
I captured the X11 traffic between |
The most visible difference between "normal" (desktop) mode and rootless mode is that in the first case, a window manager is running within the session, while in the latter case the windows are decorated through an external window manager. Maybe atoms are not exchanged correctly. |
In that case you should get the same problem when running on a normal
X server without window manager. Can you confirm?
Having written that something comes to my mind: In order to implement
rootless mode NX needs to map atoms between the local xserver and
nxagent. At this point some atoms are filtered and never mapped,
partly for performance reasons, partly because they would cause
problems. You could try and compare xlsatoms inside and outside the
session if there are any differences regarding Q* atoms.
nxagent can be built using debug flags in Rootless.c. That would show
any atom mappings going on, which might shine some more light on the
issue.
Uli
…On Thu, Sep 14, 2023 at 6:07 AM Mihai Moldovan ***@***.***> wrote:
The most visible difference between "normal" (desktop) mode and rootless mode is that in the first case, a window manager is running within the session, while in the latter case the windows are decorated through an external window manager. Maybe atoms are not exchanged correctly.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
I killed my window manager and ran
Thanks for the hint, I will dive into all of this until I reach a diagnosis. |
According to So I got back to my previous reasoning, which is: in rootless mode, the Qt-issued SendEvent X11 request with a custom-type ClientMessage is seemingly ignored. nx-libs/nx-X11/programs/Xserver/hw/nxagent/NXevents.c Lines 419 to 444 in 3ef7845
In Events.c, nx-libs/nx-X11/programs/Xserver/hw/nxagent/Events.c Lines 4502 to 4510 in 3ef7845
... which explains why nxagent ignores Qt's SendEvent with a _QT_CLOSE_CONNECTION ClientMessage only in rootless mode (and only #ifdef NXAGENT_CLIPBOARD). I tested the following quick-and-dirty workaround: --- nx-X11/programs/Xserver/hw/nxagent/NXevents.c
+++ nx-X11/programs/Xserver/hw/nxagent/NXevents.c
@@ -144,6 +144,7 @@ of the copyright holder.
#include "Windows.h"
#include "Args.h"
#include "Clipboard.h"
+#include "Atoms.h"
extern Display *nxagentDisplay;
@@ -427,8 +428,11 @@ ProcSendEvent(ClientPtr client)
if (nxagentOption(Rootless) && stuff->event.u.u.type == ClientMessage)
{
- ForwardClientMessage(client, stuff);
- return Success;
+ Atom qt_close_connection = MakeAtom("_QT_CLOSE_CONNECTION", strlen("_QT_CLOSE_CONNECTION"), False);
+ if (stuff->event.u.clientMessage.u.l.type != qt_close_connection) {
+ ForwardClientMessage(client, stuff);
+ return Success;
+ }
}
if (stuff -> event.u.u.type == SelectionNotify) ... and Qt applications now exit as expected in rootless mode. Wireshark confirms the expected Sent-ClientMessage Event was issued by nxagent and received by the Qt Application. At this stage, I believe we have a complete diagnosis. |
Great, thank you for digging deeper! That finding matches my suspicion.
However, while this fixes your specific issue we need to find out if there
are more exceptions required...
Uli
Xavier G. ***@***.***> schrieb am Sa., 23. Sept. 2023, 19:12:
… According to Atom map in context [nxagentResetAtomMap: Exiting] (and
other calls to nxagentPrintAtomMapInfo()), _QT_CLOSE_CONNECTION never
enters the atom map despite existing (with different values) in both local
and remote servers. However, I believe this is a consequence, not a cause.
So I got back to my previous reasoning, which is: in rootless mode, the
Qt-issued SendEvent X11 request with a custom-type ClientMessage is
seemingly ignored.
Based on the function name, I assumed SendEvent requests are processed by
the ProcSendEvent function:
https://github.com/ArcticaProject/nx-libs/blob/3ef7845746c4ec1ac75825ccebc17168e0400cfa/nx-X11/programs/Xserver/hw/nxagent/NXevents.c#L419-L444
In Events.c, ForwardClientMessage acts only if:
https://github.com/ArcticaProject/nx-libs/blob/3ef7845746c4ec1ac75825ccebc17168e0400cfa/nx-X11/programs/Xserver/hw/nxagent/Events.c#L4502-L4510
... which explains why nxagent ignores Qt's SendEvent with a
_QT_CLOSE_CONNECTION ClientMessage.
I tested the following quick-and-dirty workaround:
--- nx-X11/programs/Xserver/hw/nxagent/NXevents.c+++ nx-X11/programs/Xserver/hw/nxagent/NXevents.c@@ -144,6 +144,7 @@ of the copyright holder.
#include "Windows.h"
#include "Args.h"
#include "Clipboard.h"+#include "Atoms.h"
extern Display *nxagentDisplay;
@@ -427,8 +428,11 @@ ProcSendEvent(ClientPtr client)
if (nxagentOption(Rootless) && stuff->event.u.u.type == ClientMessage)
{- ForwardClientMessage(client, stuff);- return Success;+ Atom qt_close_connection = MakeAtom("_QT_CLOSE_CONNECTION", strlen("_QT_CLOSE_CONNECTION"), False);+ if (stuff->event.u.clientMessage.u.l.type != qt_close_connection) {+ ForwardClientMessage(client, stuff);+ return Success;+ }
}
if (stuff -> event.u.u.type == SelectionNotify)
... and Qt applications now exit as expected in rootless mode. Wireshark
confirms the expected Sent-ClientMessage Event was issued by nxagent and
received by the Qt Application.
At this stage, I belive we have a complete diagnosis.
Next step: discuss how to best tackle the issue.
—
Reply to this email directly, view it on GitHub
<#1065 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABQHBZB6GOI6WBHC2VFBH2DX34J77ANCNFSM6AAAAAA4R4ADGQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Here is a different fix: instead of systematically returning, ProcSendEvent() returns only if ForwardClientMessage() acknowledges it did something (or tried to do something) with the message. --- nx-X11/programs/Xserver/hw/nxagent/Events.h
+++ nx-X11/programs/Xserver/hw/nxagent/Events.h
@@ -222,6 +222,6 @@ int nxagentPendingEvents(Display *dpy);
int nxagentWaitEvents(Display *, useconds_t msec);
-void ForwardClientMessage(ClientPtr client, xSendEventReq *stuff);
+int ForwardClientMessage(ClientPtr client, xSendEventReq *stuff);
#endif /* __Events_H__ */
--- nx-X11/programs/Xserver/hw/nxagent/Events.c
+++ nx-X11/programs/Xserver/hw/nxagent/Events.c
@@ -4499,7 +4499,7 @@ int nxagentWaitEvents(Display *dpy, usec
return 1;
}
-void ForwardClientMessage(ClientPtr client, xSendEventReq *stuff)
+int ForwardClientMessage(ClientPtr client, xSendEventReq *stuff)
{
Atom netwmstate = MakeAtom("_NET_WM_STATE", strlen("_NET_WM_STATE"), False);
Atom wmchangestate = MakeAtom("WM_CHANGE_STATE", strlen("WM_CHANGE_STATE"), False);
@@ -4542,7 +4542,7 @@ void ForwardClientMessage(ClientPtr clie
#endif
}
else
- return; // ERROR!
+ return -1; // ERROR!
#ifdef DEBUG
fprintf(stderr, "%s: window [0x%lx]\n", __func__, X.xclient.window);
@@ -4562,8 +4562,10 @@ void ForwardClientMessage(ClientPtr clie
fprintf(stderr, "%s: send to window [0x%lx]\n", __func__, dest);
fprintf(stderr, "%s: return Status [%d]\n", __func__, stat);
#endif
+ return 1; // Processed/Forwarded/Sent
}
}
+ return 0; // Ignored
}
#ifdef NX_DEBUG_INPUT
--- nx-X11/programs/Xserver/hw/nxagent/NXevents.c
+++ nx-X11/programs/Xserver/hw/nxagent/NXevents.c
@@ -427,8 +427,8 @@ ProcSendEvent(ClientPtr client)
if (nxagentOption(Rootless) && stuff->event.u.u.type == ClientMessage)
{
- ForwardClientMessage(client, stuff);
- return Success;
+ if (ForwardClientMessage(client, stuff) != 0)
+ return Success;
}
if (stuff -> event.u.u.type == SelectionNotify) |
Thanks. I have broken equipment ATM so I cannot have a closer look. But I
will as soon as possible!
Uli
…On Thu, Sep 28, 2023 at 1:51 AM Xavier G. ***@***.***> wrote:
Here is a different fix: instead of systematically returning,
ProcSendEvent() returns only if ForwardClientMessage() acknowledges it did
something (or tried to do something) with the message.
--- nx-X11/programs/Xserver/hw/nxagent/Events.h+++ nx-X11/programs/Xserver/hw/nxagent/Events.h@@ -222,6 +222,6 @@ int nxagentPendingEvents(Display *dpy);
int nxagentWaitEvents(Display *, useconds_t msec);
-void ForwardClientMessage(ClientPtr client, xSendEventReq *stuff);+int ForwardClientMessage(ClientPtr client, xSendEventReq *stuff);
#endif /* __Events_H__ */--- nx-X11/programs/Xserver/hw/nxagent/Events.c+++ nx-X11/programs/Xserver/hw/nxagent/Events.c@@ -4499,7 +4499,7 @@ int nxagentWaitEvents(Display *dpy, usec
return 1;
}
-void ForwardClientMessage(ClientPtr client, xSendEventReq *stuff)+int ForwardClientMessage(ClientPtr client, xSendEventReq *stuff)
{
Atom netwmstate = MakeAtom("_NET_WM_STATE", strlen("_NET_WM_STATE"), False);
Atom wmchangestate = MakeAtom("WM_CHANGE_STATE", strlen("WM_CHANGE_STATE"), False);@@ -4542,7 +4542,7 @@ void ForwardClientMessage(ClientPtr clie
#endif
}
else- return; // ERROR!+ return -1; // ERROR!
#ifdef DEBUG
fprintf(stderr, "%s: window [0x%lx]\n", __func__, X.xclient.window);@@ -4562,8 +4562,10 @@ void ForwardClientMessage(ClientPtr clie
fprintf(stderr, "%s: send to window [0x%lx]\n", __func__, dest);
fprintf(stderr, "%s: return Status [%d]\n", __func__, stat);
#endif+ return 1; // Processed/Forwarded/Sent
}
}+ return 0; // Ignored
}
#ifdef NX_DEBUG_INPUT--- nx-X11/programs/Xserver/hw/nxagent/NXevents.c+++ nx-X11/programs/Xserver/hw/nxagent/NXevents.c@@ -427,8 +427,8 @@ ProcSendEvent(ClientPtr client)
if (nxagentOption(Rootless) && stuff->event.u.u.type == ClientMessage)
{- ForwardClientMessage(client, stuff);- return Success;+ if (ForwardClientMessage(client, stuff) != 0)+ return Success;
}
if (stuff -> event.u.u.type == SelectionNotify)
—
Reply to this email directly, view it on GitHub
<#1065 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABQHBZA47DCQ6OBBIH7AC7TX4S3XTANCNFSM6AAAAAA4R4ADGQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
The problem I just mentioned in #1015 might be related to this. We both issues should be fixable in one go. |
This looks like a Qt bug, but since it only happens with
nxagent -R
and not withnxagent
, I would like to discuss it here before reporting the issue to the Qt organisation.What is happening? It seems Qt applications work fine with nxagent as a nested X server, with or without the
-R
(rootless) option... until they need to exit, at which point their windows disappear but the process seems to hang, possibly waiting for something from nxagent.How to reproduce?
nxagent -ac -R :222
A small "hello" button should appear. Clicking it is supposed to make the application exit. It works fine in normal mode but in rootless mode, the process will not exit.
The application outputs some warnings on stderr right after it starts (and long before it even tries to exit). So far there is no reason to believe they are related with this issue.
A brief inspection of the stacks hints that thread 1 is waiting for thread 2 and thread 2 is waiting for something from the X server:
Backtrace for thread 1
Backtrace for thread 2
Questions:
The text was updated successfully, but these errors were encountered: