-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[lldb] Fixed the error unable to launch a GDB server
in API tests
#98833
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
Conversation
TestPlatformLaunchGDBServer.py runs ldb-server w/o --min-gdbserver-port, --max-gdbserver-port or --gdbserver-port, so gdbserver_portmap is empty and gdbserver_portmap.GetNextAvailablePort() will return 0. Do not pass 0 to portmap_for_child in this case. Added few asserts in GDBRemoteCommunicationServerPlatform::PortMap to avoid this in the future. This patch fixes llvm#97537. It seems StartDebugserverProcess() ignores the port anyway and parameters --min-gdbserver-port, --max-gdbserver-port and --gdbserver-port are useless at all, but it is out of scope of this patch.
@llvm/pr-subscribers-lldb Author: Dmitry Vasilyev (slydiman) ChangesTestPlatformLaunchGDBServer.py runs ldb-server w/o parameters This patch fixes #97537. It seems StartDebugserverProcess() ignores the port anyway and parameters Full diff: https://github.com/llvm/llvm-project/pull/98833.diff 2 Files Affected:
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 5285ec1d3db4e..65f1cc12ba307 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -46,11 +46,13 @@ using namespace lldb_private;
GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
uint16_t max_port) {
+ assert(min_port);
for (; min_port < max_port; ++min_port)
m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
}
void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
+ assert(port);
// Do not modify existing mappings
m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
}
diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp
index cfd0a3797d810..7148a1d2a3094 100644
--- a/lldb/tools/lldb-server/lldb-platform.cpp
+++ b/lldb/tools/lldb-server/lldb-platform.cpp
@@ -313,9 +313,11 @@ int main_platform(int argc, char *argv[]) {
GDBRemoteCommunicationServerPlatform::PortMap portmap_for_child;
llvm::Expected<uint16_t> available_port =
gdbserver_portmap.GetNextAvailablePort();
- if (available_port)
- portmap_for_child.AllowPort(*available_port);
- else {
+ if (available_port) {
+ // GetNextAvailablePort() may return 0 if gdbserver_portmap is empty.
+ if (*available_port)
+ portmap_for_child.AllowPort(*available_port);
+ } else {
llvm::consumeError(available_port.takeError());
fprintf(stderr,
"no available gdbserver port for connection - dropping...\n");
@@ -352,7 +354,7 @@ int main_platform(int argc, char *argv[]) {
if (platform.IsConnected()) {
if (inferior_arguments.GetArgumentCount() > 0) {
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
- std::optional<uint16_t> port = 0;
+ std::optional<uint16_t> port;
std::string socket_name;
Status error = platform.LaunchGDBServer(inferior_arguments,
"", // hostname
|
Did you consider making My guess is that this port dance is complicated enough as it is, and |
GetNextAvailablePort() returns 0 in case of the empty map. LaunchGDBServer() does not update the map with the pid if the port is 0. So 0 is the special value which means if GetNextAvailablePort() allocated the port 0 after AllowPort(0), it will never be freed because of conditions llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp Lines 209 to 221 in 7b135f7
|
The best solution is simply to remove all code related to gdb port mapping, because it does not work at all. Try to run
If gdb port parameters specified, now it causes issues like #97537, but a random port will be used for connection anyway. If no gdb port parameters specified, the port map must be empty and must stay empty. AllowPort(0) makes the port map not empty and causes an unexpected behavior. This patch fixes this issue. |
On the one hand I agree, on the other I use this feature a lot and it works for my limited uses (the race condition aside). If I can find an alternative that allows me to run tests in enironments with limited port forwarding, I'd be happy for it to be removed.
Not sure what you mean here, I don't see that happening on my machine:
Perhaps I am spelling the port option differently, or you mean a lldb-server gdbserver launched by a platform ignores the port. |
Agreed, so silent UB would just be making things worse. |
So, this patch fixes that issue, right?
It seems it depends on the system.
Finally we just configured VMs to use a network bridge with own IP w/o any port limits and do not map ports manually to host's ports anymore. Note I'm working on a patch to fix #97537 and all port mapping related issues. The idea is to use threads for platform mode and use a common port map for all connections instead of making a new |
Yes I think so, give me some time to test it myself. |
I tested this with the port mapping I usually use for simulator development and it works fine. Thanks for the fix. |
…98833) Summary: TestPlatformLaunchGDBServer.py runs `ldb-server` w/o parameters `--min-gdbserver-port`, `--max-gdbserver-port` or `--gdbserver-port`. So `gdbserver_portmap` is empty and `gdbserver_portmap.GetNextAvailablePort()` will return 0. Do not call `portmap_for_child.AllowPort(0)` in this case. Otherwise `portmap_for_child.GetNextAvailablePort()` will allocate and never free the port 0 and next call `portmap_for_child.GetNextAvailablePort()` will fail. Added few asserts in `GDBRemoteCommunicationServerPlatform::PortMap` to avoid such issue in the future. This patch fixes a bug added in #88845. The behaviour is very close to #97537 w/o parameters `--min-gdbserver-port`, `--max-gdbserver-port` and `--gdbserver-port`. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250877
TestPlatformLaunchGDBServer.py runs
ldb-server
w/o parameters--min-gdbserver-port
,--max-gdbserver-port
or--gdbserver-port
. Sogdbserver_portmap
is empty andgdbserver_portmap.GetNextAvailablePort()
will return 0. Do not callportmap_for_child.AllowPort(0)
in this case. Otherwiseportmap_for_child.GetNextAvailablePort()
will allocate and never free the port 0 and next callportmap_for_child.GetNextAvailablePort()
will fail.Added few asserts in
GDBRemoteCommunicationServerPlatform::PortMap
to avoid such issue in the future.This patch fixes a bug added in #88845. The behaviour is very close to #97537 w/o parameters
--min-gdbserver-port
,--max-gdbserver-port
and--gdbserver-port
.