Package: X2go 4.1.2.3
Also on 4.1.2.2
MacOS Tahoe 26.7.2
Qt 4.8.7, Qt 5.15.9
Hello,
I recently ran into an issue connecting to our college's Linux server with X2go, it seemed like it was trying to connect to invalid TCP ports. Chat GPT assisted in patching and getting it working for me, and I am providing the summary here:
X2Go on macOS Tahoe – Troubleshooting Summary and Fix
1. The original problem
I was unable to connect to my college's Linux server (bellagio.csn.edu) using X2Go Client on my MacBook Air.
My configuration was:
Component
Version
macOS
Tahoe 26.7.2
X2Go Client
4.1.2.2
NXProxy
3.5.99.20
XQuartz
2.8.6
Mac architecture
Apple Silicon (ARM64)
The connection worked successfully from my Windows computer, and SSH connections from my Mac also worked.
The original X2Go error was:
Info: Connecting to remote host 'localhost:65536'.
Port 65536 is invalid because the maximum TCP port is 65535.
2. Root cause
We investigated the X2Go Client 4.1.2.2 source code and eventually reproduced the problem independently.
The relevant function was:
bool ONMainWindow::isServerRunning(int port)
{
QTcpSocket tcpSocket(0);
tcpSocket.connectToHost("127.0.0.1", port);
if (tcpSocket.waitForConnected(1000))
{
tcpSocket.close();
return true;
}
return false;
}
This function determines whether a local TCP port is already occupied.
However, our testing on macOS Tahoe demonstrated unexpected Qt behavior: QTcpSocket::waitForConnected() reported successful connections to ports where no listening service existed.
We verified this using a standalone Qt test and compared it against Python socket tests and lsof.
As a result, X2Go incorrectly believed that every candidate local port was occupied.
Its port-selection loop kept incrementing until it reached 65536.
We reproduced the same problem with X2Go Client 4.1.2.3, so simply upgrading the client wasn't sufficient.
3. The actual fix we applied
We installed X2Go Client 4.1.2.3 through MacPorts and modified its source code.
Change 1: Replace the port availability test on macOS.
Instead of using QTcpSocket::connectToHost(), we used QTcpServer::listen().
The replacement code was:
#ifdef Q_OS_DARWIN
// Determine port availability by binding a local listening socket.
if (port < 1 || port > 65535)
return true;
QTcpServer tcpServer;
if (tcpServer.listen(QHostAddress::LocalHost,
static_cast(port)))
{
tcpServer.close();
return false;
}
return true;
#else
QTcpSocket tcpSocket(0);
tcpSocket.connectToHost("127.0.0.1", port);
if (tcpSocket.waitForConnected(1000))
{
tcpSocket.close();
return true;
}
return false;
#endif
The new implementation attempts to bind and listen on the candidate port:
*
If binding succeeds, the port is available.
*
If binding fails, the port is treated as unavailable.
This avoids the unexpected connection-test behavior we observed on macOS.
Change 2: Prevent invalid TCP port selection.
We also modified the graphics-port selection loop.
Original:
localGraphicPort = resumingSession.grPort;
int iport = localGraphicPort.toInt() + 1000;
while (iport == resumingSession.sndPort.toInt() ||
iport == resumingSession.fsPort.toInt() ||
isServerRunning(iport))
++iport;
localGraphicPort = QString::number(iport);
Patched:
localGraphicPort = resumingSession.grPort;
int iport = localGraphicPort.toInt() + 1000;
while (iport <= 65535 &&
(iport == resumingSession.sndPort.toInt() ||
iport == resumingSession.fsPort.toInt() ||
isServerRunning(iport)))
++iport;
if (iport > 65535)
{
QMessageBox::critical(
this,
tr("X2Go Client"),
tr("No available local TCP port could be found for this session.")
);
return;
}
localGraphicPort = QString::number(iport);
This ensures X2Go never attempts to use a port outside the valid TCP range.
4. Additional macOS Tahoe workaround
There was a separate compatibility issue involving XQuartz.
Starting with macOS 26.4, Apple changed the location of the XQuartz display socket.
Our college provided a launcher that worked around this by:
1.
Detecting the active XQuartz socket.
2.
Creating a temporary symbolic link under /tmp/launchXXXXXX.
3.
Setting the DISPLAY environment variable to the compatible path.
4.
Launching X2Go Client.
5.
Cleaning up the temporary directory afterward.
We retained this workaround and used it when launching our patched client.
5. Successful result
Resolved
We rebuilt the patched X2Go Client 4.1.2.3 through MacPorts and tested the staged application before installing or replacing anything.
The successful debug log showed:
Starting tunnel via SshProcess object 2:
"localhost":50729 -> "localhost":51729
Then:
Direct tunnel: waiting for connections on "localhost":51729
And finally:
Info: Connecting to remote host 'localhost:51729'.
Info: Connected to remote proxy on FD#5.
The client successfully connected to the college Linux server and launched Geany.
No changes to the college Linux server were necessary.
6. Final working setup
We copied the patched application to:
~/Applications/X2Go Client Patched.app
We also created a desktop launcher:
~/Desktop/X2Go-Tahoe.command
The launcher automatically applies the XQuartz compatibility workaround and starts the patched client.
The original college-provided launcher and original X2Go installation were left intact.
Final summary
Problem
Resolution
macOS Tahoe changed XQuartz socket location
College-provided launcher creates compatibility symlink
Qt port detection incorrectly reported ports as occupied
Replaced connection-based test with QTcpServer::listen() on macOS
X2Go selected invalid port 65536
Added TCP port-range validation
X2Go timed out connecting to NXProxy
Resolved by selecting a valid local tunnel port
Original installation needed to be preserved
Created separate patched application and desktop launcher
The key technical fix was replacing X2Go's macOS QTcpSocket::waitForConnected() port-availability check with QTcpServer::listen().
One maintenance note: the fix was applied to our MacPorts source build, not upstream X2Go. A future MacPorts upgrade may overwrite it, so keep a copy of the patched source and original backup (onmainwindow.cpp.pre-darwin-portfix).
This is also a useful bug report to share with the X2Go developers and your college IT department, particularly because we reproduced the problem on both 4.1.2.2 and 4.1.2.3.