<div dir="ltr">Hi Pavel, I think you are on the right track in that it already does seem to wait for the gdbserver to be up using a pipe.<div><br></div><div>In StartDebugserverProcess it seems like there is a pipe created to tell when the server is running.  Here is a comment:</div><div><br></div><div><div>    // socket_pipe is used by debug server to communicate back either</div><div>    // TCP port or domain socket name which it listens on.</div><div>    // The second purpose of the pipe to serve as a synchronization point -</div><div>    // once data is written to the pipe, debug server is up and running.</div></div><div><br></div><div>However, it looks like specifying --min-gdbserver-port and --max-gdbserver-port cause the pipe to not be used for some reason.</div><div><br></div><div>Here is the gdbserver invocation when I don't specify the gdb min and max port:</div><div>> lldb-server gdbserver tcp://<myip>:0 --native-regs --pipe 6</div><div><br></div><div>And here is the gdbserver invocation when I do specify the gdb port:<br><div>> lldb-server gdbserver tcp://<myip>:<mygdbport> --native-regs</div></div><div><br></div><div>Its not obvious to me from looking at the code why this is being skipped.  But I will debug further why this argument is not used in this case.</div><div><br></div><div>Thanks,<br>Chris</div><div><br><div class="gmail_quote"><div dir="ltr">On Tue, Nov 28, 2017 at 5:25 AM Pavel Labath <<a href="mailto:labath@google.com">labath@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 27 November 2017 at 20:33, Christopher Book via lldb-dev<br>
<<a href="mailto:lldb-dev@lists.llvm.org" target="_blank">lldb-dev@lists.llvm.org</a>> wrote:<br>
> Greetings, I've been using liblldb to remotely debug to a linux server with<br>
> port forwarding.  To do this, I start lldb-server to with --listen<br>
> specifying a localhost port, as well as with ----min-gdbserver-port and<br>
> --max-gdbserver-port to specify a specific port for use by 'gdb remote'.<br>
> Both ports are forwarded to the remote PC, where liblldb connects to<br>
> localhost.<br>
><br>
> This generally works fine, but there is a race condition.  When the client<br>
> tells lldb-server to start gdb-remote, the port is returned to the client<br>
> which may try to connect before the gdb-remote process is actually<br>
> listening.<br>
Are you sure this is what's happening? Looking at lldb-server source<br>
code, I see that it starts listening on lldb-gdbserver.cpp:320<br>
      error = acceptor_up->Listen(1);<br>
      if (error.Fail()) {<br>
        fprintf(stderr, "failed to listen: %s\n", error.AsCString());<br>
        exit(1);<br>
      }<br>
and the port number is written out only later, on line 334:<br>
      error = acceptor_up->Listen(1);<br>
      if (error.Fail()) {<br>
        fprintf(stderr, "failed to listen: %s\n", error.AsCString());<br>
        exit(1);<br>
      }<br>
<br>
After listen returns the connection by your port forwarder should not<br>
be rejected, and it can only connect once it knows the port to connect<br>
to.<br>
<br>
<br>
That's not to say that connecting through port forwarders is easy. For<br>
android debugging, we also have to setup port forwarding with adb, and<br>
we need to do some quite elaborate dances to make sure that the<br>
connection is reliable and race free (see<br>
PlatformAndroidRemoteGDBServer::MakeConnectURL) -- however this is to<br>
resolve a different issue (allocating the port on the local side from<br>
which to do the forwarding), which does not sound like the problem you<br>
describe.<br>
<br>
<br>
> I would like to submit a patch, but first check to see if this solution<br>
> would be acceptable:<br>
> - Include the handshake within the connection retry loop.<br>
> - This means fully disconnecting the re-establishing the connection in the<br>
> loop if the handshake fails.<br>
> - Changing the timeout check to be based on a total absolute time instead of<br>
> 50 iterations with a 100ms sleep.<br>
><br>
> Thoughts?<br>
><br>
> Alternatives could be:<br>
> - Have lldb-server delay responding to the 'start gdb server' request until<br>
> it could tell (somehow) that the process is listening.<br>
> - A sleep of some kind on the client side after starting the server but<br>
> before trying to connect.<br>
><br>
<br>
The most port-forwarder-friendly solution (and one that I've been<br>
wanting to implement for a while, but never got around to it) I can<br>
think of is to not require a second port for the llgs connection. It<br>
could work approximately like this:<br>
- we add a new packet type to the lldb-server platform instance: (e.g.<br>
qExecGDBServer)<br>
- upon receiving this packet, the platform instance would exec the<br>
gdb-server instance, and pass it the existing socket file descriptor<br>
(via a command line argument or whatever)<br>
- the gdb-server instance would start up with the connection primed<br>
and ready, and would not need to do any listening and writing back the<br>
port number, etc.<br>
- the lldb client would end up with it's "platform" connection being<br>
connected to llgs, and would have to create a new platform connection<br>
(or it could create a scratch platform solely for the purpose of<br>
exec()ing the llgs). Either way, the second connection would be to the<br>
exact same address and port as the first one, so there should not be<br>
any extra forwarding setup necessary.<br>
<br>
The details of this will need to be thought through (e.g., who should<br>
send the first packet after the exec()? how to detect an error? should<br>
the connection start in no-ack mode?), but I don't think it should be<br>
too complicated overall. And all port-forwarding users would benefit<br>
from that (we could delete the android-specific code I mentioned, and<br>
you could stop mucking with --max-gdbserver-port).<br>
<br>
What do you think about that?<br>
<br>
pavel<br>
</blockquote></div></div></div>