From P.Klenze@gsi.de  Tue Sep 22 19:14:56 2026
Received: (at submit) by bugs.x2go.org; 22 Sep 2026 17:15:07 +0000
X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on
	ymir.das-netzwerkteam.de
X-Spam-Level: 
X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00,DMARC_PASS,
	RCVD_IN_DNSWL_BLOCKED,RCVD_IN_ZEN_BLOCKED_OPENDNS,SPF_HELO_PASS
	autolearn=ham autolearn_force=no version=4.0.0
Received: from lxmtout1.gsi.de (lxmtout1.gsi.de [140.181.3.111])
	by ymir.das-netzwerkteam.de (Postfix) with ESMTPS id A6A5D5DB22
	for <submit@bugs.x2go.org>; Tue, 22 Sep 2026 19:14:54 +0200 (CEST)
Received: from localhost (localhost [127.0.0.1])
	by lxmtout1.gsi.de (Postfix) with ESMTP id 5409320522EE
	for <submit@bugs.x2go.org>; Tue, 22 Sep 2026 19:14:54 +0200 (CEST)
X-Virus-Scanned: Debian amavis at lxmtout1.gsi.de
Received: from lxmtout1.gsi.de ([127.0.0.1])
 by localhost (lxmtout1.gsi.de [127.0.0.1]) (amavis, port 10024) with LMTP
 id 1KFE22Af1FOD for <submit@bugs.x2go.org>;
 Tue, 22 Sep 2026 19:14:54 +0200 (CEST)
Received: from srvEX6.campus.gsi.de (unknown [10.10.4.96])
	(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by lxmtout1.gsi.de (Postfix) with ESMTPS id 3C05320522E7
	for <submit@bugs.x2go.org>; Tue, 22 Sep 2026 19:14:54 +0200 (CEST)
Received: from [172.21.34.9] (140.181.3.12) by srvEX6.campus.gsi.de
 (10.10.4.96) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 22 Sep
 2026 19:14:54 +0200
Message-ID: <c2b3b9e3-f435-433b-a463-18107a192e08@gsi.de>
Date: Tue, 22 Sep 2026 19:14:53 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
To: <submit@bugs.x2go.org>
Content-Language: en-US
From: Philipp Klenze <p.klenze@gsi.de>
Subject: [llm-coauthored] Session resume hangs/fails
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: 7bit
X-Originating-IP: [140.181.3.12]
X-ClientProxiedBy: srvEX6.Campus.gsi.de (10.10.4.96) To srvEX6.campus.gsi.de
 (10.10.4.96)

Package: x2goserver
Version: 4.1.0.6-0x2go1+git20230818.1994+12.main.1
(As reported by dpkg -l.)

Begin human-written summary.

It appears that by design or through some as-of-yet untraced error, 
x2goagent does not serve the X11 connection in between receiving a 
SIGHUP and starting to listen() on the port specified in options and the 
connection to that port being made, or otherwise a 60s timeout being 
reached.

However, the resume script contains a call to setxkbmap.

So the process on my system is the following:

1.    Client executes x2goresume-session on the server
1.1   x2goresume-session sends SIGHUP to x2goagent
1.2   x2goresume-session runs setxkbmap (for some reason)
1.2.1 setxkbmap hangs (because X11 is not responding)

X.    After 60 seconds without a connect() attempt, a watchdog then 
closes the socket and resumes headless operation.

1.2.2 setxkbmap exits (the X11 request having been handled)
1.3   x2goresume-session exits
2.    Client tries to connect to the x2go through ssh port forwarding
2.1   That connection fails due to that socket having just been closed 
in step X.

The fix is just to not run setxkbmap (or use the diff below). If the 
behavior "X11 blocks between catching HUP and accept()" is not 
intentional, then that would be the underlying bug.

This is also the underlying issue for me encountering #1637 in x2goclient.

End human-written summary -- rest is Claude (cut by Philipp for length).

--------------------------------------------------------------------
NOTE ON HOW THIS WAS PRODUCED
--------------------------------------------------------------------
Same as the earlier reports in this thread: debugging (strace, gdb,
manual instrumentation of local script copies) done together with an
LLM assistant (Claude) at my direction. I ran every command and
verified every finding myself; the writeup itself is LLM-coauthored.

--------------------------------------------------------------------
SUMMARY
--------------------------------------------------------------------
Resuming a suspended session was failing outright, or taking 60+ seconds 
and then failing, with the classic symptom:

   ssh_channel_open_forward failed: Channel opening failure:
   channel N error (2) Connection refused

...and, on the server side (from sshd's own log):

   sshd[N]: error: connect_to localhost port NNNNN: failed.
   sshd[N]: channel_by_id: 0: bad id: channel free
   sshd[N]: Disconnecting user ...: ieof packet referred to
   nonexistent channel 0

This is the exact signature of the long-standing bug #302 ("No
session resume", filed 2013, merged with duplicates #206 and #263,
eventually reassigned to nxagent and marked fixed in nxagent
3.5.0.25 back in June 2014). I'm running nxagent 3.5.99.26/27 --
far newer than the version that was supposedly fixed -- and hit the
identical symptom regardless. Extensive strace-level debugging (see
below) found two real, distinct, previously-undocumented-as-far-as-
I-can-tell root causes, neither of which matches what the 2014 fix
addressed (that fix was about NX-protocol-level socket cleanup
timing in nxagent's own code; what I found is different).


--------------------------------------------------------------------
ROOT CAUSE: a backgrounded setxkbmap call in x2goresume-session was 
holding the SSH exec channel open for the same ~60 seconds, well after 
the script itself had finished and exited
--------------------------------------------------------------------
This is the one that turned a "narrow, occasionally-missed race"
into "consistently fails by about a second every single time" for
my setup, and it's a plain script bug, not anything in nxagent.

x2goresume-session sets client-side keyboard settings in one of two
ways depending on configuration:

   if [[ "${set_kbd}" != '0' ]] && [[ "${kbd_type_val}" = 'auto' ]]; then
       export DISPLAY=":${x2go_display}.0"
       x2gosetkeyboard "${session_name}" &>'/dev/null' &
   fi
   if [[ "${set_kbd}" != '0'  &&  "${kbd_type_val}" != 'auto' ]]; then
       ...
       export DISPLAY=":${x2go_display}.0"
       setxkbmap ${xkbmap_arg}
   fi

The "auto" branch is correctly backgrounded *and* has its
stdout/stderr redirected to /dev/null before being sent to the
background. The other branch (explicit keyboard type, which is my
setup) originally just ran setxkbmap synchronously -- meaning it
was directly in the resume script's own execution path, and since
setxkbmap is an ordinary X11 client, it blocks for however long
nxagent takes to answer it (see root cause #1) -- up to the full 60
seconds, every time.

The actual fix, matching the pattern the "auto" branch already used
correctly:

   setxkbmap ${xkbmap_arg} &>'/dev/null' &

Redirect first, then background -- exactly mirroring the sibling
branch that was already correct. With this in place, resume works
reliably for me.

--------------------------------------------------------------------
PATCH
--------------------------------------------------------------------
Against the 4.1.0.6-ish x2goresume-session (adjust context lines to
match your exact version; the actual line content to find/replace
is what matters):

--- a/x2goserver/bin/x2goresume-session
+++ b/x2goserver/bin/x2goresume-session
@@ -349,7 +349,7 @@
  		export DISPLAY=":${x2go_display}.0"
-		setxkbmap ${xkbmap_arg}
+		setxkbmap ${xkbmap_arg} &>'/dev/null' &
  	fi

--------------------------------------------------------------------
RELATIONSHIP TO #302
--------------------------------------------------------------------
Given the identical downstream symptom, it's worth being explicit
that this is not a rediscovery of #302. That bug was fixed at the
NX-protocol/socket-cleanup level in nxagent 3.5.0.25, over a decade
ago; I'm on a much newer nxagent and still hit the same-looking
failure via a completely different mechanism (a script-level file-
descriptor/channel-lifetime issue, not anything in NX's own socket
handling). Possibly worth a decision from whoever owns this area on
whether these should be tracked as one long-running issue or split
out -- I'd lean toward a new report given the root cause is
unrelated to what #302's fix addressed, but happy to defer to
however the project prefers to track it.

