forked from OSchip/llvm-project
Add domain socket support to gdb-remote protocol and lldb-server.
http://reviews.llvm.org/D13881 llvm-svn: 250933
This commit is contained in:
parent
526b5f9cd4
commit
9fe526c2e7
|
@ -103,6 +103,8 @@
|
|||
2579065C1BD0488100178368 /* TCPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065A1BD0488100178368 /* TCPSocket.cpp */; };
|
||||
2579065D1BD0488100178368 /* UDPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065B1BD0488100178368 /* UDPSocket.cpp */; };
|
||||
2579065F1BD0488D00178368 /* DomainSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065E1BD0488D00178368 /* DomainSocket.cpp */; };
|
||||
257906641BD5AFD000178368 /* Acceptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257906621BD5AFD000178368 /* Acceptor.cpp */; };
|
||||
257906651BD5AFD000178368 /* Acceptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 257906631BD5AFD000178368 /* Acceptor.h */; };
|
||||
257E47171AA56C2000A62F81 /* ModuleCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257E47151AA56C2000A62F81 /* ModuleCache.cpp */; };
|
||||
25EF23781AC09B3700908DF0 /* AdbClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25EF23751AC09AD800908DF0 /* AdbClient.cpp */; };
|
||||
260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
|
||||
|
@ -1207,6 +1209,8 @@
|
|||
2579065A1BD0488100178368 /* TCPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCPSocket.cpp; sourceTree = "<group>"; };
|
||||
2579065B1BD0488100178368 /* UDPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UDPSocket.cpp; sourceTree = "<group>"; };
|
||||
2579065E1BD0488D00178368 /* DomainSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DomainSocket.cpp; sourceTree = "<group>"; };
|
||||
257906621BD5AFD000178368 /* Acceptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acceptor.cpp; path = "tools/lldb-server/Acceptor.cpp"; sourceTree = "<group>"; };
|
||||
257906631BD5AFD000178368 /* Acceptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Acceptor.h; path = "tools/lldb-server/Acceptor.h"; sourceTree = "<group>"; };
|
||||
257E47151AA56C2000A62F81 /* ModuleCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleCache.cpp; path = source/Utility/ModuleCache.cpp; sourceTree = "<group>"; };
|
||||
257E47161AA56C2000A62F81 /* ModuleCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleCache.h; path = source/Utility/ModuleCache.h; sourceTree = "<group>"; };
|
||||
25EF23751AC09AD800908DF0 /* AdbClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdbClient.cpp; sourceTree = "<group>"; };
|
||||
|
@ -5588,6 +5592,8 @@
|
|||
E769331B1A94D10E00C73337 /* lldb-server */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
257906621BD5AFD000178368 /* Acceptor.cpp */,
|
||||
257906631BD5AFD000178368 /* Acceptor.h */,
|
||||
6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */,
|
||||
6D762BED1B1605CD006C929D /* LLDBServerUtilities.h */,
|
||||
E769331D1A94D18100C73337 /* lldb-server.cpp */,
|
||||
|
@ -5703,6 +5709,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */,
|
||||
257906651BD5AFD000178368 /* Acceptor.h in Headers */,
|
||||
260A63171861008E00FECF8E /* IOHandler.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -6539,6 +6546,7 @@
|
|||
268900E513353E6F00698AC0 /* UnwindTable.cpp in Sources */,
|
||||
268900E613353E6F00698AC0 /* Variable.cpp in Sources */,
|
||||
268900E713353E6F00698AC0 /* VariableList.cpp in Sources */,
|
||||
257906641BD5AFD000178368 /* Acceptor.cpp in Sources */,
|
||||
268900E813353E6F00698AC0 /* ABI.cpp in Sources */,
|
||||
4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */,
|
||||
26AB92121819D74600E63F3E /* DWARFDataExtractor.cpp in Sources */,
|
||||
|
|
|
@ -50,8 +50,6 @@
|
|||
#include "lldb/Host/common/TCPSocket.h"
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
|
||||
#include "Utility/UriParser.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
@ -171,20 +169,6 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
|
|||
// unix://SOCKNAME
|
||||
return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr);
|
||||
}
|
||||
else if (strstr(s, "adb://") == s)
|
||||
{
|
||||
int port = -1;
|
||||
std::string scheme, host, path;
|
||||
if (!UriParser::Parse(s, scheme, host, port, path))
|
||||
{
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorStringWithFormat("Failed to parse URL '%s'", s);
|
||||
return eConnectionStatusError;
|
||||
}
|
||||
std::ostringstream host_and_port;
|
||||
host_and_port << "localhost:" << port;
|
||||
return ConnectTCP(host_and_port.str().c_str(), error_ptr);
|
||||
}
|
||||
else if (strstr(s, "connect://") == s)
|
||||
{
|
||||
return ConnectTCP(s + strlen("connect://"), error_ptr);
|
||||
|
@ -197,6 +181,11 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
|
|||
{
|
||||
return ConnectUDP(s + strlen("udp://"), error_ptr);
|
||||
}
|
||||
else if (strstr(s, "unix-connect://") == s)
|
||||
{
|
||||
// unix-connect://SOCKNAME
|
||||
return NamedSocketConnect(s + strlen("unix-connect://"), error_ptr);
|
||||
}
|
||||
#ifndef LLDB_DISABLE_POSIX
|
||||
else if (strstr(s, "fd://") == s)
|
||||
{
|
||||
|
|
|
@ -144,6 +144,19 @@ AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_p
|
|||
return ReadResponseStatus ();
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::SetPortForwarding (const uint16_t local_port, const char* remote_socket_name)
|
||||
{
|
||||
char message[PATH_MAX];
|
||||
snprintf (message, sizeof (message), "forward:tcp:%d;localfilesystem:%s", local_port, remote_socket_name);
|
||||
|
||||
const auto error = SendDeviceMessage (message);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
return ReadResponseStatus ();
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::DeletePortForwarding (const uint16_t local_port)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
Error
|
||||
SetPortForwarding (const uint16_t local_port, const uint16_t remote_port);
|
||||
|
||||
Error
|
||||
SetPortForwarding (const uint16_t local_port, const char* remote_socket_name);
|
||||
|
||||
Error
|
||||
DeletePortForwarding (const uint16_t local_port);
|
||||
|
||||
|
|
|
@ -196,8 +196,7 @@ PlatformAndroid::ConnectRemote(Args& args)
|
|||
return Error("URL is null.");
|
||||
if (!UriParser::Parse(url, scheme, host, port, path))
|
||||
return Error("Invalid URL: %s", url);
|
||||
if (scheme == "adb")
|
||||
m_device_id = host;
|
||||
m_device_id = host;
|
||||
|
||||
auto error = PlatformLinux::ConnectRemote(args);
|
||||
if (error.Success())
|
||||
|
|
|
@ -24,7 +24,10 @@ using namespace platform_android;
|
|||
static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform
|
||||
|
||||
static Error
|
||||
ForwardPortWithAdb (const uint16_t local_port, const uint16_t remote_port, std::string& device_id)
|
||||
ForwardPortWithAdb (const uint16_t local_port,
|
||||
const uint16_t remote_port,
|
||||
const char* remote_socket_name,
|
||||
std::string& device_id)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
|
||||
|
||||
|
@ -37,7 +40,16 @@ ForwardPortWithAdb (const uint16_t local_port, const uint16_t remote_port, std::
|
|||
if (log)
|
||||
log->Printf("Connected to Android device \"%s\"", device_id.c_str ());
|
||||
|
||||
return adb.SetPortForwarding(local_port, remote_port);
|
||||
if (remote_port != 0)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("Forwarding remote TCP port %d to local TCP port %d", remote_port, local_port);
|
||||
return adb.SetPortForwarding(local_port, remote_port);
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", remote_socket_name, local_port);
|
||||
return adb.SetPortForwarding(local_port, remote_socket_name);
|
||||
}
|
||||
|
||||
static Error
|
||||
|
@ -72,16 +84,24 @@ PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer ()
|
|||
DeleteForwardPortWithAdb(it.second, m_device_id);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PlatformAndroidRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
|
||||
bool
|
||||
PlatformAndroidRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url)
|
||||
{
|
||||
uint16_t remote_port = m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
|
||||
if (remote_port == 0)
|
||||
return remote_port;
|
||||
uint16_t remote_port = 0;
|
||||
std::string socket_name;
|
||||
if (!m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, remote_port, socket_name))
|
||||
return false;
|
||||
|
||||
uint16_t local_port = 0;
|
||||
auto error = SetPortForwarding (pid, remote_port, local_port);
|
||||
return error.Success() ? local_port : 0;
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
|
||||
|
||||
auto error = MakeConnectURL (pid,
|
||||
remote_port,
|
||||
socket_name.c_str (),
|
||||
connect_url);
|
||||
if (error.Success() && log)
|
||||
log->Printf("gdbserver connect URL: %s", connect_url.c_str());
|
||||
|
||||
return error.Success();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -106,21 +126,22 @@ PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
|
|||
return Error("URL is null.");
|
||||
if (!UriParser::Parse (url, scheme, host, remote_port, path))
|
||||
return Error("Invalid URL: %s", url);
|
||||
if (scheme == "adb")
|
||||
m_device_id = host;
|
||||
m_device_id = host;
|
||||
|
||||
std::string connect_url;
|
||||
auto error = MakeConnectURL (g_remote_platform_pid,
|
||||
(remote_port < 0) ? 0 : remote_port,
|
||||
path.c_str (),
|
||||
connect_url);
|
||||
|
||||
uint16_t local_port = 0;
|
||||
auto error = SetPortForwarding (g_remote_platform_pid, remote_port, local_port);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
const std::string new_url = MakeUrl(
|
||||
scheme.c_str(), host.c_str(), local_port, path.c_str());
|
||||
args.ReplaceArgumentAtIndex (0, new_url.c_str ());
|
||||
args.ReplaceArgumentAtIndex (0, connect_url.c_str ());
|
||||
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
|
||||
if (log)
|
||||
log->Printf("Rewritten URL: %s", new_url.c_str());
|
||||
log->Printf("Rewritten platform connect URL: %s", connect_url.c_str());
|
||||
|
||||
error = PlatformRemoteGDBServer::ConnectRemote(args);
|
||||
if (error.Fail ())
|
||||
|
@ -156,9 +177,10 @@ PlatformAndroidRemoteGDBServer::DeleteForwardPort (lldb::pid_t pid)
|
|||
}
|
||||
|
||||
Error
|
||||
PlatformAndroidRemoteGDBServer::SetPortForwarding(const lldb::pid_t pid,
|
||||
const uint16_t remote_port,
|
||||
uint16_t &local_port)
|
||||
PlatformAndroidRemoteGDBServer::MakeConnectURL(const lldb::pid_t pid,
|
||||
const uint16_t remote_port,
|
||||
const char* remote_socket_name,
|
||||
std::string& connect_url)
|
||||
{
|
||||
static const int kAttempsNum = 5;
|
||||
|
||||
|
@ -168,35 +190,21 @@ PlatformAndroidRemoteGDBServer::SetPortForwarding(const lldb::pid_t pid,
|
|||
// adding the loop to mitigate such problem.
|
||||
for (auto i = 0; i < kAttempsNum; ++i)
|
||||
{
|
||||
uint16_t local_port = 0;
|
||||
error = FindUnusedPort(local_port);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
error = ForwardPortWithAdb(local_port, remote_port, m_device_id);
|
||||
error = ForwardPortWithAdb(local_port, remote_port, remote_socket_name, m_device_id);
|
||||
if (error.Success())
|
||||
{
|
||||
m_port_forwards[pid] = local_port;
|
||||
std::ostringstream url_str;
|
||||
url_str << "connect://localhost:" << local_port;
|
||||
connect_url = url_str.str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
std::string
|
||||
PlatformAndroidRemoteGDBServer::MakeUrl(const char* scheme,
|
||||
const char* hostname,
|
||||
uint16_t port,
|
||||
const char* path)
|
||||
{
|
||||
std::ostringstream hostname_str;
|
||||
if (!strcmp(scheme, "adb"))
|
||||
hostname_str << "[" << hostname << "]";
|
||||
else
|
||||
hostname_str << hostname;
|
||||
|
||||
return PlatformRemoteGDBServer::MakeUrl(scheme,
|
||||
hostname_str.str().c_str(),
|
||||
port,
|
||||
path);
|
||||
}
|
||||
|
|
|
@ -40,8 +40,8 @@ protected:
|
|||
std::string m_device_id;
|
||||
std::map<lldb::pid_t, uint16_t> m_port_forwards;
|
||||
|
||||
uint16_t
|
||||
LaunchGDBserverAndGetPort (lldb::pid_t &pid) override;
|
||||
bool
|
||||
LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) override;
|
||||
|
||||
bool
|
||||
KillSpawnedProcess (lldb::pid_t pid) override;
|
||||
|
@ -49,14 +49,11 @@ protected:
|
|||
void
|
||||
DeleteForwardPort (lldb::pid_t pid);
|
||||
|
||||
std::string
|
||||
MakeUrl(const char* scheme,
|
||||
const char* hostname,
|
||||
uint16_t port,
|
||||
const char* path) override;
|
||||
|
||||
Error
|
||||
SetPortForwarding(const lldb::pid_t pid, const uint16_t remote_port, uint16_t &local_port);
|
||||
MakeConnectURL(const lldb::pid_t pid,
|
||||
const uint16_t remote_port,
|
||||
const char* remote_socket_name,
|
||||
std::string& connect_url);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (PlatformAndroidRemoteGDBServer);
|
||||
|
|
|
@ -573,9 +573,8 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
|
|||
if (IsConnected())
|
||||
{
|
||||
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
|
||||
uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
|
||||
|
||||
if (port == 0)
|
||||
std::string connect_url;
|
||||
if (!LaunchGDBServer(debugserver_pid, connect_url))
|
||||
{
|
||||
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
|
||||
}
|
||||
|
@ -606,8 +605,6 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
|
|||
|
||||
if (process_sp)
|
||||
{
|
||||
std::string connect_url =
|
||||
MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);
|
||||
error = process_sp->ConnectRemote (nullptr, connect_url.c_str());
|
||||
// Retry the connect remote one time...
|
||||
if (error.Fail())
|
||||
|
@ -632,23 +629,36 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
|
|||
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
|
||||
bool
|
||||
PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url)
|
||||
{
|
||||
ArchSpec remote_arch = GetRemoteSystemArchitecture ();
|
||||
llvm::Triple &remote_triple = remote_arch.GetTriple ();
|
||||
|
||||
uint16_t port = 0;
|
||||
std::string socket_name;
|
||||
bool launch_result = false;
|
||||
if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS)
|
||||
{
|
||||
// When remote debugging to iOS, we use a USB mux that always talks
|
||||
// to localhost, so we will need the remote debugserver to accept connections
|
||||
// only from localhost, no matter what our current hostname is
|
||||
return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
|
||||
launch_result = m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, port, socket_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// All other hosts should use their actual hostname
|
||||
return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL);
|
||||
launch_result = m_gdb_client.LaunchGDBServer (nullptr, pid, port, socket_name);
|
||||
}
|
||||
|
||||
if (!launch_result)
|
||||
return false;
|
||||
|
||||
connect_url = MakeGdbServerUrl(m_platform_scheme,
|
||||
m_platform_hostname,
|
||||
port,
|
||||
(socket_name.empty()) ? nullptr : socket_name.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -669,9 +679,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,
|
|||
if (IsConnected())
|
||||
{
|
||||
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
|
||||
uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
|
||||
|
||||
if (port == 0)
|
||||
std::string connect_url;
|
||||
if (!LaunchGDBServer(debugserver_pid, connect_url))
|
||||
{
|
||||
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
|
||||
}
|
||||
|
@ -699,11 +708,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,
|
|||
// The darwin always currently uses the GDB remote debugger plug-in
|
||||
// so even when debugging locally we are debugging remotely!
|
||||
process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
|
||||
|
||||
if (process_sp)
|
||||
{
|
||||
std::string connect_url =
|
||||
MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);
|
||||
error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
|
||||
if (error.Success())
|
||||
{
|
||||
|
@ -950,7 +956,8 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
|
|||
std::string
|
||||
PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme,
|
||||
const std::string &platform_hostname,
|
||||
uint16_t port)
|
||||
uint16_t port,
|
||||
const char* socket_name)
|
||||
{
|
||||
const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
|
||||
const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
|
||||
|
@ -960,17 +967,19 @@ PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme,
|
|||
return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
|
||||
override_hostname ? override_hostname : platform_hostname.c_str(),
|
||||
port + port_offset,
|
||||
nullptr);
|
||||
socket_name);
|
||||
}
|
||||
|
||||
std::string
|
||||
PlatformRemoteGDBServer::MakeUrl(const char* scheme,
|
||||
const char* hostname,
|
||||
uint16_t port,
|
||||
const char* path)
|
||||
const char* hostname,
|
||||
uint16_t port,
|
||||
const char* path)
|
||||
{
|
||||
StreamString result;
|
||||
result.Printf("%s://%s:%u", scheme, hostname, port);
|
||||
result.Printf("%s://%s", scheme, hostname);
|
||||
if (port != 0)
|
||||
result.Printf(":%u", port);
|
||||
if (path)
|
||||
result.Write(path, strlen(path));
|
||||
return result.GetString();
|
||||
|
|
|
@ -225,11 +225,12 @@ protected:
|
|||
|
||||
lldb::UnixSignalsSP m_remote_signals_sp;
|
||||
|
||||
// Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on
|
||||
// failure. Subclasses should override this method if they want to do extra actions before or
|
||||
// after launching the lldb-gdbserver.
|
||||
virtual uint16_t
|
||||
LaunchGDBserverAndGetPort (lldb::pid_t &pid);
|
||||
// Launch the debug server on the remote host - caller connects to launched
|
||||
// debug server using connect_url.
|
||||
// Subclasses should override this method if they want to do extra actions before or
|
||||
// after launching the debug server.
|
||||
virtual bool
|
||||
LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url);
|
||||
|
||||
virtual bool
|
||||
KillSpawnedProcess (lldb::pid_t pid);
|
||||
|
@ -244,7 +245,8 @@ private:
|
|||
std::string
|
||||
MakeGdbServerUrl(const std::string &platform_scheme,
|
||||
const std::string &platform_hostname,
|
||||
uint16_t port);
|
||||
uint16_t port,
|
||||
const char* socket_name);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
|
||||
|
||||
|
|
|
@ -1112,17 +1112,15 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
|
|||
}
|
||||
|
||||
Error
|
||||
GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
||||
uint16_t in_port,
|
||||
GDBRemoteCommunication::StartDebugserverProcess (const char *url,
|
||||
Platform *platform,
|
||||
ProcessLaunchInfo &launch_info,
|
||||
uint16_t &out_port)
|
||||
uint16_t *port)
|
||||
{
|
||||
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
|
||||
if (log)
|
||||
log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);
|
||||
log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
|
||||
|
||||
out_port = in_port;
|
||||
Error error;
|
||||
// If we locate debugserver, keep that located version around
|
||||
static FileSpec g_debugserver_file_spec;
|
||||
|
@ -1193,17 +1191,9 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
debugserver_args.AppendArgument("gdbserver");
|
||||
#endif
|
||||
|
||||
// If a host and port is supplied then use it
|
||||
char host_and_port[128];
|
||||
if (hostname)
|
||||
{
|
||||
snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
|
||||
debugserver_args.AppendArgument(host_and_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
host_and_port[0] = '\0';
|
||||
}
|
||||
// If a url is supplied then use it
|
||||
if (url)
|
||||
debugserver_args.AppendArgument(url);
|
||||
|
||||
// use native registers, not the GDB registers
|
||||
debugserver_args.AppendArgument("--native-regs");
|
||||
|
@ -1214,11 +1204,18 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
}
|
||||
|
||||
llvm::SmallString<PATH_MAX> named_pipe_path;
|
||||
Pipe port_pipe;
|
||||
// socket_pipe is used by debug server to communicate back either
|
||||
// TCP port or domain socket name which it listens on.
|
||||
// The second purpose of the pipe to serve as a synchronization point -
|
||||
// once data is written to the pipe, debug server is up and running.
|
||||
Pipe socket_pipe;
|
||||
|
||||
if (in_port == 0)
|
||||
// port is null when debug server should listen on domain socket -
|
||||
// we're not interested in port value but rather waiting for debug server
|
||||
// to become available.
|
||||
if ((port != nullptr && *port == 0) || port == nullptr)
|
||||
{
|
||||
if (host_and_port[0])
|
||||
if (url)
|
||||
{
|
||||
// Create a temporary file to get the stdout/stderr and redirect the
|
||||
// output of the command into this file. We will later read this file
|
||||
|
@ -1227,7 +1224,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
#if defined(__APPLE__)
|
||||
// Binding to port zero, we need to figure out what port it ends up
|
||||
// using using a named pipe...
|
||||
error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
|
||||
error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
|
||||
if (error.Fail())
|
||||
{
|
||||
if (log)
|
||||
|
@ -1241,7 +1238,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
#else
|
||||
// Binding to port zero, we need to figure out what port it ends up
|
||||
// using using an unnamed pipe...
|
||||
error = port_pipe.CreateNew(true);
|
||||
error = socket_pipe.CreateNew(true);
|
||||
if (error.Fail())
|
||||
{
|
||||
if (log)
|
||||
|
@ -1250,10 +1247,10 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
__FUNCTION__, error.AsCString());
|
||||
return error;
|
||||
}
|
||||
int write_fd = port_pipe.GetWriteFileDescriptor();
|
||||
int write_fd = socket_pipe.GetWriteFileDescriptor();
|
||||
debugserver_args.AppendArgument("--pipe");
|
||||
debugserver_args.AppendArgument(std::to_string(write_fd).c_str());
|
||||
launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor());
|
||||
launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -1270,11 +1267,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
|
||||
ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
|
||||
// Wait for 10 seconds to resolve the bound port
|
||||
out_port = connection->GetListeningPort(10);
|
||||
if (out_port > 0)
|
||||
*port = connection->GetListeningPort(10);
|
||||
if (*port > 0)
|
||||
{
|
||||
char port_cstr[32];
|
||||
snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
|
||||
snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", *port);
|
||||
// Send the host and port down that debugserver and specify an option
|
||||
// so that it connects back to the port we are listening to in this process
|
||||
debugserver_args.AppendArgument("--reverse-connect");
|
||||
|
@ -1343,11 +1340,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
|
||||
error = Host::LaunchProcess(launch_info);
|
||||
|
||||
if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
|
||||
if (error.Success() &&
|
||||
launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
|
||||
{
|
||||
if (named_pipe_path.size() > 0)
|
||||
{
|
||||
error = port_pipe.OpenAsReader(named_pipe_path, false);
|
||||
error = socket_pipe.OpenAsReader(named_pipe_path, false);
|
||||
if (error.Fail())
|
||||
if (log)
|
||||
log->Printf("GDBRemoteCommunication::%s() "
|
||||
|
@ -1355,24 +1353,24 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
__FUNCTION__, named_pipe_path.c_str(), error.AsCString());
|
||||
}
|
||||
|
||||
if (port_pipe.CanWrite())
|
||||
port_pipe.CloseWriteFileDescriptor();
|
||||
if (port_pipe.CanRead())
|
||||
if (socket_pipe.CanWrite())
|
||||
socket_pipe.CloseWriteFileDescriptor();
|
||||
if (socket_pipe.CanRead())
|
||||
{
|
||||
char port_cstr[256];
|
||||
char port_cstr[PATH_MAX] = {0};
|
||||
port_cstr[0] = '\0';
|
||||
size_t num_bytes = sizeof(port_cstr);
|
||||
// Read port from pipe with 10 second timeout.
|
||||
error = port_pipe.ReadWithTimeout(port_cstr, num_bytes,
|
||||
error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes,
|
||||
std::chrono::seconds{10}, num_bytes);
|
||||
if (error.Success())
|
||||
if (error.Success() && (port != nullptr))
|
||||
{
|
||||
assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
|
||||
out_port = StringConvert::ToUInt32(port_cstr, 0);
|
||||
*port = StringConvert::ToUInt32(port_cstr, 0);
|
||||
if (log)
|
||||
log->Printf("GDBRemoteCommunication::%s() "
|
||||
"debugserver listens %u port",
|
||||
__FUNCTION__, out_port);
|
||||
"debugserver listens %u port",
|
||||
__FUNCTION__, *port);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1382,12 +1380,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
|
|||
__FUNCTION__, named_pipe_path.c_str(), error.AsCString());
|
||||
|
||||
}
|
||||
port_pipe.Close();
|
||||
socket_pipe.Close();
|
||||
}
|
||||
|
||||
if (named_pipe_path.size() > 0)
|
||||
{
|
||||
const auto err = port_pipe.Delete(named_pipe_path);
|
||||
const auto err = socket_pipe.Delete(named_pipe_path);
|
||||
if (err.Fail())
|
||||
{
|
||||
if (log)
|
||||
|
|
|
@ -167,11 +167,10 @@ public:
|
|||
// supplied connection URL.
|
||||
//------------------------------------------------------------------
|
||||
Error
|
||||
StartDebugserverProcess (const char *hostname,
|
||||
uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit
|
||||
StartDebugserverProcess (const char *url,
|
||||
Platform *platform, // If non NULL, then check with the platform for the GDB server binary if it can't be located
|
||||
ProcessLaunchInfo &launch_info,
|
||||
uint16_t &out_port);
|
||||
uint16_t *port);
|
||||
|
||||
void
|
||||
DumpHistory(Stream &strm);
|
||||
|
|
|
@ -3315,10 +3315,16 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
|
|||
return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname)
|
||||
bool
|
||||
GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname,
|
||||
lldb::pid_t &pid,
|
||||
uint16_t &port,
|
||||
std::string &socket_name)
|
||||
{
|
||||
pid = LLDB_INVALID_PROCESS_ID;
|
||||
port = 0;
|
||||
socket_name.clear();
|
||||
|
||||
StringExtractorGDBRemote response;
|
||||
StreamString stream;
|
||||
stream.PutCString("qLaunchGDBServer;");
|
||||
|
@ -3343,22 +3349,30 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const
|
|||
|
||||
// give the process a few seconds to startup
|
||||
GDBRemoteCommunication::ScopedTimeout timeout (*this, 10);
|
||||
|
||||
|
||||
if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
|
||||
{
|
||||
std::string name;
|
||||
std::string value;
|
||||
uint16_t port = 0;
|
||||
StringExtractor extractor;
|
||||
while (response.GetNameColonValue(name, value))
|
||||
{
|
||||
if (name.compare("port") == 0)
|
||||
port = StringConvert::ToUInt32(value.c_str(), 0, 0);
|
||||
else if (name.compare("pid") == 0)
|
||||
pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
|
||||
else if (name.compare("socket_name") == 0)
|
||||
{
|
||||
extractor.GetStringRef().swap(value);
|
||||
extractor.SetFilePos(0);
|
||||
extractor.GetHexByteString(value);
|
||||
|
||||
socket_name = value;
|
||||
}
|
||||
}
|
||||
return port;
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -114,8 +114,11 @@ public:
|
|||
bool
|
||||
GetLaunchSuccess (std::string &error_str);
|
||||
|
||||
uint16_t
|
||||
LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname);
|
||||
bool
|
||||
LaunchGDBServer (const char *remote_accept_hostname,
|
||||
lldb::pid_t &pid,
|
||||
uint16_t &port,
|
||||
std::string &socket_name);
|
||||
|
||||
bool
|
||||
KillSpawnedProcess (lldb::pid_t pid);
|
||||
|
|
|
@ -15,14 +15,20 @@
|
|||
// C++ Includes
|
||||
#include <cstring>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
|
||||
// Other libraries and framework includes
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/StreamGDBRemote.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Core/StructuredData.h"
|
||||
#include "lldb/Host/Config.h"
|
||||
#include "lldb/Host/ConnectionFileDescriptor.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Host/HostInfo.h"
|
||||
#include "lldb/Host/StringConvert.h"
|
||||
#include "lldb/Target/FileAction.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
|
@ -40,8 +46,9 @@ using namespace lldb_private::process_gdb_remote;
|
|||
//----------------------------------------------------------------------
|
||||
// GDBRemoteCommunicationServerPlatform constructor
|
||||
//----------------------------------------------------------------------
|
||||
GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() :
|
||||
GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol) :
|
||||
GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"),
|
||||
m_socket_protocol(socket_protocol),
|
||||
m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_platform_sp (Platform::GetHostPlatform ()),
|
||||
m_port_map (),
|
||||
|
@ -138,11 +145,24 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD
|
|||
bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
|
||||
UNUSED_IF_ASSERT_DISABLED(ok);
|
||||
assert(ok);
|
||||
Error error = StartDebugserverProcess (platform_ip.c_str(),
|
||||
port,
|
||||
|
||||
std::string socket_name;
|
||||
std::ostringstream url;
|
||||
|
||||
uint16_t* port_ptr = &port;
|
||||
if (m_socket_protocol == Socket::ProtocolTcp)
|
||||
url << platform_ip << ":" << port;
|
||||
else
|
||||
{
|
||||
socket_name = GetDomainSocketPath("gdbserver").GetPath();
|
||||
url << socket_name;
|
||||
port_ptr = nullptr;
|
||||
}
|
||||
|
||||
Error error = StartDebugserverProcess (url.str().c_str(),
|
||||
nullptr,
|
||||
debugserver_launch_info,
|
||||
port);
|
||||
port_ptr);
|
||||
|
||||
lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
|
||||
|
||||
|
@ -165,11 +185,16 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD
|
|||
if (log)
|
||||
log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
|
||||
|
||||
char response[256];
|
||||
const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
|
||||
assert (response_len < (int)sizeof(response));
|
||||
PacketResult packet_result = SendPacketNoLock (response, response_len);
|
||||
StreamGDBRemote response;
|
||||
response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
|
||||
if (!socket_name.empty())
|
||||
{
|
||||
response.PutCString("socket_name:");
|
||||
response.PutCStringAsRawHex8(socket_name.c_str());
|
||||
response.PutChar(';');
|
||||
}
|
||||
|
||||
PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
|
||||
if (packet_result != PacketResult::Success)
|
||||
{
|
||||
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
|
||||
|
@ -494,6 +519,36 @@ GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
|
|||
return false;
|
||||
}
|
||||
|
||||
const FileSpec&
|
||||
GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
|
||||
{
|
||||
static FileSpec g_domainsocket_dir;
|
||||
static std::once_flag g_once_flag;
|
||||
|
||||
std::call_once(g_once_flag, []() {
|
||||
const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
|
||||
if (domainsocket_dir_env != nullptr)
|
||||
g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
|
||||
else
|
||||
HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
|
||||
});
|
||||
|
||||
return g_domainsocket_dir;
|
||||
}
|
||||
|
||||
FileSpec
|
||||
GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
|
||||
{
|
||||
llvm::SmallString<PATH_MAX> socket_path;
|
||||
llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
|
||||
|
||||
FileSpec socket_path_spec(GetDomainSocketDir());
|
||||
socket_path_spec.AppendPathComponent(socket_name.c_str());
|
||||
|
||||
llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
|
||||
return FileSpec(socket_path.c_str(), false);
|
||||
}
|
||||
|
||||
void
|
||||
GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "GDBRemoteCommunicationServerCommon.h"
|
||||
|
||||
#include "lldb/Host/Socket.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -23,7 +25,7 @@ class GDBRemoteCommunicationServerPlatform :
|
|||
public:
|
||||
typedef std::map<uint16_t, lldb::pid_t> PortMap;
|
||||
|
||||
GDBRemoteCommunicationServerPlatform();
|
||||
GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol);
|
||||
|
||||
virtual
|
||||
~GDBRemoteCommunicationServerPlatform();
|
||||
|
@ -61,6 +63,7 @@ public:
|
|||
SetPortOffset (uint16_t port_offset);
|
||||
|
||||
protected:
|
||||
const Socket::SocketProtocol m_socket_protocol;
|
||||
Mutex m_spawned_pids_mutex;
|
||||
std::set<lldb::pid_t> m_spawned_pids;
|
||||
lldb::PlatformSP m_platform_sp;
|
||||
|
@ -103,6 +106,12 @@ private:
|
|||
int signal,
|
||||
int status);
|
||||
|
||||
static const FileSpec&
|
||||
GetDomainSocketDir();
|
||||
|
||||
static FileSpec
|
||||
GetDomainSocketPath(const char* prefix);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// For GDBRemoteCommunicationServerPlatform only
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -3562,15 +3562,22 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
|
|||
// Set hostname being NULL to do the reverse connect where debugserver
|
||||
// will bind to port zero and it will communicate back to us the port
|
||||
// that we will connect to
|
||||
const char *hostname = NULL;
|
||||
const char *hostname = nullptr;
|
||||
uint16_t port = 0;
|
||||
#endif
|
||||
|
||||
error = m_gdb_comm.StartDebugserverProcess (hostname,
|
||||
port,
|
||||
StreamString url_str;
|
||||
const char* url = nullptr;
|
||||
if (hostname != nullptr)
|
||||
{
|
||||
url_str.Printf("%s:%u", hostname, port);
|
||||
url = url_str.GetData();
|
||||
}
|
||||
|
||||
error = m_gdb_comm.StartDebugserverProcess (url,
|
||||
GetTarget().GetPlatform().get(),
|
||||
debugserver_launch_info,
|
||||
port);
|
||||
&port);
|
||||
|
||||
if (error.Success ())
|
||||
m_debugserver_pid = debugserver_launch_info.GetProcessID();
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
//===-- Acceptor.cpp --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Acceptor.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Host/ConnectionFileDescriptor.h"
|
||||
#include "lldb/Host/common/TCPSocket.h"
|
||||
#include "lldb/Host/posix/DomainSocket.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::lldb_server;
|
||||
using namespace llvm;
|
||||
|
||||
Error
|
||||
Acceptor::Listen(int backlog)
|
||||
{
|
||||
return m_listener_socket_up->Listen(StringRef(m_name.c_str()),
|
||||
backlog);
|
||||
}
|
||||
|
||||
Error
|
||||
Acceptor::Accept(const bool child_processes_inherit, Connection *&conn)
|
||||
{
|
||||
Socket* conn_socket = nullptr;
|
||||
auto error = m_listener_socket_up->Accept(StringRef(m_name.c_str()),
|
||||
child_processes_inherit,
|
||||
conn_socket);
|
||||
if (error.Success())
|
||||
conn = new ConnectionFileDescriptor(conn_socket);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Socket::SocketProtocol
|
||||
Acceptor::GetSocketProtocol() const
|
||||
{
|
||||
return m_listener_socket_up->GetSocketProtocol();
|
||||
}
|
||||
|
||||
std::string
|
||||
Acceptor::GetLocalSocketId() const
|
||||
{
|
||||
return m_local_socket_id();
|
||||
}
|
||||
|
||||
std::unique_ptr<Acceptor>
|
||||
Acceptor::Create(StringRef name, const bool child_processes_inherit, Error &error)
|
||||
{
|
||||
error.Clear();
|
||||
|
||||
LocalSocketIdFunc local_socket_id;
|
||||
std::unique_ptr<Socket> listener_socket = nullptr;
|
||||
std::string host_str;
|
||||
std::string port_str;
|
||||
int32_t port = INT32_MIN;
|
||||
if (Socket::DecodeHostAndPort (name, host_str, port_str, port, &error))
|
||||
{
|
||||
auto tcp_socket = new TCPSocket(child_processes_inherit, error);
|
||||
local_socket_id = [tcp_socket]() {
|
||||
auto local_port = tcp_socket->GetLocalPortNumber();
|
||||
return (local_port != 0) ? std::to_string(local_port) : "";
|
||||
};
|
||||
listener_socket.reset(tcp_socket);
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string socket_name = name;
|
||||
local_socket_id = [socket_name](){
|
||||
return socket_name;
|
||||
};
|
||||
listener_socket.reset(new DomainSocket(child_processes_inherit, error));
|
||||
}
|
||||
|
||||
if (error.Success())
|
||||
return std::unique_ptr<Acceptor>(
|
||||
new Acceptor(std::move(listener_socket), name, local_socket_id));
|
||||
|
||||
return std::unique_ptr<Acceptor>();
|
||||
}
|
||||
|
||||
Acceptor::Acceptor(std::unique_ptr<Socket> &&listener_socket,
|
||||
StringRef name,
|
||||
const LocalSocketIdFunc &local_socket_id)
|
||||
: m_listener_socket_up(std::move(listener_socket)),
|
||||
m_name(name.str()),
|
||||
m_local_socket_id(local_socket_id)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
//===-- Acceptor.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef lldb_server_Acceptor_h_
|
||||
#define lldb_server_Acceptor_h_
|
||||
|
||||
#include "lldb/Core/Connection.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Host/Socket.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
class StringRef;
|
||||
}
|
||||
|
||||
namespace lldb_private {
|
||||
namespace lldb_server {
|
||||
|
||||
class Acceptor
|
||||
{
|
||||
public:
|
||||
virtual ~Acceptor() = default;
|
||||
|
||||
Error
|
||||
Listen(int backlog);
|
||||
|
||||
Error
|
||||
Accept(const bool child_processes_inherit, Connection *&conn);
|
||||
|
||||
static std::unique_ptr<Acceptor>
|
||||
Create(llvm::StringRef name, const bool child_processes_inherit, Error &error);
|
||||
|
||||
Socket::SocketProtocol GetSocketProtocol() const;
|
||||
|
||||
// Returns either TCP port number as string or domain socket path.
|
||||
// Empty string is returned in case of error.
|
||||
std::string GetLocalSocketId() const;
|
||||
|
||||
private:
|
||||
typedef std::function<std::string()> LocalSocketIdFunc;
|
||||
|
||||
Acceptor(std::unique_ptr<Socket> &&listener_socket,
|
||||
llvm::StringRef name,
|
||||
const LocalSocketIdFunc &local_socket_id);
|
||||
|
||||
const std::unique_ptr<Socket> m_listener_socket_up;
|
||||
const std::string m_name;
|
||||
const LocalSocketIdFunc m_local_socket_id;
|
||||
};
|
||||
|
||||
} // namespace lldb_server
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // lldb_server_Acceptor_h_
|
|
@ -18,24 +18,18 @@ include_directories(../../source)
|
|||
|
||||
include(../../cmake/LLDBDependencies.cmake)
|
||||
|
||||
if (BUILD_SHARED_LIBS )
|
||||
add_lldb_executable(lldb-server
|
||||
add_lldb_executable(lldb-server
|
||||
Acceptor.cpp
|
||||
lldb-gdbserver.cpp
|
||||
lldb-platform.cpp
|
||||
lldb-server.cpp
|
||||
LLDBServerUtilities.cpp
|
||||
)
|
||||
)
|
||||
|
||||
if (BUILD_SHARED_LIBS )
|
||||
target_link_libraries(lldb-server liblldb)
|
||||
target_link_libraries(lldb-server ${LLDB_SYSTEM_LIBS})
|
||||
else()
|
||||
add_lldb_executable(lldb-server
|
||||
lldb-gdbserver.cpp
|
||||
lldb-platform.cpp
|
||||
lldb-server.cpp
|
||||
LLDBServerUtilities.cpp
|
||||
)
|
||||
|
||||
# The Darwin linker doesn't understand --start-group/--end-group.
|
||||
if (LLDB_LINKER_SUPPORTS_GROUPS)
|
||||
target_link_libraries(lldb-server
|
||||
|
|
|
@ -24,18 +24,16 @@
|
|||
// Other libraries and framework includes
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
#include "lldb/Core/ConnectionMachPort.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Host/ConnectionFileDescriptor.h"
|
||||
#include "lldb/Host/HostGetOpt.h"
|
||||
#include "lldb/Host/HostThread.h"
|
||||
#include "lldb/Host/OptionParser.h"
|
||||
#include "lldb/Host/Pipe.h"
|
||||
#include "lldb/Host/Socket.h"
|
||||
#include "lldb/Host/StringConvert.h"
|
||||
#include "lldb/Host/ThreadLauncher.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
#include "Acceptor.h"
|
||||
#include "LLDBServerUtilities.h"
|
||||
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
|
||||
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
|
||||
|
@ -54,15 +52,6 @@ using namespace lldb_private;
|
|||
using namespace lldb_private::lldb_server;
|
||||
using namespace lldb_private::process_gdb_remote;
|
||||
|
||||
// lldb-gdbserver state
|
||||
|
||||
namespace
|
||||
{
|
||||
HostThread s_listen_thread;
|
||||
std::unique_ptr<ConnectionFileDescriptor> s_listen_connection_up;
|
||||
std::string s_listen_url;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// option descriptors for getopt_long_only()
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -263,64 +252,16 @@ handle_launch (GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const cha
|
|||
}
|
||||
}
|
||||
|
||||
static lldb::thread_result_t
|
||||
ListenThread (lldb::thread_arg_t /* arg */)
|
||||
{
|
||||
Error error;
|
||||
|
||||
if (s_listen_connection_up)
|
||||
{
|
||||
// Do the listen on another thread so we can continue on...
|
||||
if (s_listen_connection_up->Connect(s_listen_url.c_str(), &error) != eConnectionStatusSuccess)
|
||||
s_listen_connection_up.reset();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Error
|
||||
StartListenThread (const char *hostname, uint16_t port)
|
||||
{
|
||||
Error error;
|
||||
if (s_listen_thread.IsJoinable())
|
||||
{
|
||||
error.SetErrorString("listen thread already running");
|
||||
}
|
||||
else
|
||||
{
|
||||
char listen_url[512];
|
||||
if (hostname && hostname[0])
|
||||
snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port);
|
||||
else
|
||||
snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
|
||||
|
||||
s_listen_url = listen_url;
|
||||
s_listen_connection_up.reset (new ConnectionFileDescriptor ());
|
||||
s_listen_thread = ThreadLauncher::LaunchThread(listen_url, ListenThread, nullptr, &error);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool
|
||||
JoinListenThread ()
|
||||
{
|
||||
if (s_listen_thread.IsJoinable())
|
||||
s_listen_thread.Join(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
Error
|
||||
WritePortToPipe(Pipe &port_pipe, const uint16_t port)
|
||||
writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id)
|
||||
{
|
||||
char port_str[64];
|
||||
const auto port_str_len = ::snprintf(port_str, sizeof(port_str), "%u", port);
|
||||
|
||||
size_t bytes_written = 0;
|
||||
// Write the port number as a C string with the NULL terminator.
|
||||
return port_pipe.Write(port_str, port_str_len + 1, bytes_written);
|
||||
return port_pipe.Write(socket_id.c_str(), socket_id.size(), bytes_written);
|
||||
}
|
||||
|
||||
Error
|
||||
writePortToPipe(const char *const named_pipe_path, const uint16_t port)
|
||||
writeSocketIdToPipe(const char *const named_pipe_path, const std::string &socket_id)
|
||||
{
|
||||
Pipe port_name_pipe;
|
||||
// Wait for 10 seconds for pipe to be opened.
|
||||
|
@ -328,17 +269,17 @@ writePortToPipe(const char *const named_pipe_path, const uint16_t port)
|
|||
std::chrono::seconds{10});
|
||||
if (error.Fail())
|
||||
return error;
|
||||
return WritePortToPipe(port_name_pipe, port);
|
||||
return writeSocketIdToPipe(port_name_pipe, socket_id);
|
||||
}
|
||||
|
||||
Error
|
||||
writePortToPipe(int unnamed_pipe_fd, const uint16_t port)
|
||||
writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return Error("Unnamed pipes are not supported on Windows.");
|
||||
#else
|
||||
Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd};
|
||||
return WritePortToPipe(port_pipe, port);
|
||||
return writeSocketIdToPipe(port_pipe, socket_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -370,14 +311,8 @@ ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server
|
|||
connection_port = final_host_and_port.substr (colon_pos + 1);
|
||||
connection_portno = StringConvert::ToUInt32 (connection_port.c_str (), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "failed to parse host and port from connection string '%s'\n", final_host_and_port.c_str ());
|
||||
display_usage (progname, subcommand);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
std::unique_ptr<ConnectionFileDescriptor> connection_up;
|
||||
std::unique_ptr<Connection> connection_up;
|
||||
|
||||
if (reverse_connect)
|
||||
{
|
||||
|
@ -410,66 +345,51 @@ ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server
|
|||
}
|
||||
else
|
||||
{
|
||||
// llgs will listen for connections on the given port from the given address.
|
||||
// Start the listener on a new thread. We need to do this so we can resolve the
|
||||
// bound listener port.
|
||||
StartListenThread(connection_host.c_str (), static_cast<uint16_t> (connection_portno));
|
||||
printf ("Listening to port %s for a connection from %s...\n", connection_port.c_str (), connection_host.c_str ());
|
||||
|
||||
// If we have a named pipe to write the port number back to, do that now.
|
||||
if (named_pipe_path && named_pipe_path[0] && connection_portno == 0)
|
||||
std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(final_host_and_port, false, error));
|
||||
if (error.Fail())
|
||||
{
|
||||
const uint16_t bound_port = s_listen_connection_up->GetListeningPort (10);
|
||||
if (bound_port > 0)
|
||||
{
|
||||
error = writePortToPipe (named_pipe_path, bound_port);
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "failed to write to the named pipe \'%s\': %s", named_pipe_path, error.AsCString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "unable to get the bound port for the listening connection\n");
|
||||
}
|
||||
fprintf(stderr, "failed to create acceptor: %s", error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// If we have an unnamed pipe to write the port number back to, do that now.
|
||||
if (unnamed_pipe_fd >= 0 && connection_portno == 0)
|
||||
error = acceptor_up->Listen(1);
|
||||
if (error.Fail())
|
||||
{
|
||||
const uint16_t bound_port = s_listen_connection_up->GetListeningPort(10);
|
||||
if (bound_port > 0)
|
||||
fprintf(stderr, "failed to listen: %s\n", error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
const std::string socket_id = acceptor_up->GetLocalSocketId();
|
||||
if (!socket_id.empty())
|
||||
{
|
||||
// If we have a named pipe to write the socket id back to, do that now.
|
||||
if (named_pipe_path && named_pipe_path[0])
|
||||
{
|
||||
error = writePortToPipe(unnamed_pipe_fd, bound_port);
|
||||
error = writeSocketIdToPipe (named_pipe_path, socket_id);
|
||||
if (error.Fail ())
|
||||
fprintf (stderr, "failed to write to the named pipe \'%s\': %s",
|
||||
named_pipe_path, error.AsCString());
|
||||
}
|
||||
// If we have an unnamed pipe to write the socket id back to, do that now.
|
||||
else if (unnamed_pipe_fd >= 0)
|
||||
{
|
||||
error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id);
|
||||
if (error.Fail())
|
||||
{
|
||||
fprintf(stderr, "failed to write to the unnamed pipe: %s",
|
||||
error.AsCString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "unable to get the bound port for the listening connection\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Join the listener thread.
|
||||
if (!JoinListenThread ())
|
||||
{
|
||||
fprintf (stderr, "failed to join the listener thread\n");
|
||||
display_usage (progname, subcommand);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
// Ensure we connected.
|
||||
if (s_listen_connection_up)
|
||||
connection_up = std::move(s_listen_connection_up);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ());
|
||||
display_usage (progname, subcommand);
|
||||
exit (1);
|
||||
fprintf (stderr, "unable to get the socket id for the listening connection\n");
|
||||
}
|
||||
|
||||
Connection* conn = nullptr;
|
||||
error = acceptor_up->Accept(false, conn);
|
||||
if (error.Fail())
|
||||
{
|
||||
printf ("failed to accept new connection: %s\n", error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
connection_up.reset(conn);
|
||||
}
|
||||
error = gdb_server.InitializeConnection (std::move(connection_up));
|
||||
if (error.Fail())
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include <fstream>
|
||||
|
||||
// Other libraries and framework includes
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/FileUtilities.h"
|
||||
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Host/ConnectionFileDescriptor.h"
|
||||
#include "lldb/Host/FileSpec.h"
|
||||
|
@ -30,8 +33,7 @@
|
|||
#include "lldb/Host/HostGetOpt.h"
|
||||
#include "lldb/Host/OptionParser.h"
|
||||
#include "lldb/Host/common/TCPSocket.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/FileUtilities.h"
|
||||
#include "Acceptor.h"
|
||||
#include "LLDBServerUtilities.h"
|
||||
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
|
||||
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
|
||||
|
@ -61,7 +63,7 @@ static struct option g_long_options[] =
|
|||
{ "gdbserver-port", required_argument, NULL, 'P' },
|
||||
{ "min-gdbserver-port", required_argument, NULL, 'm' },
|
||||
{ "max-gdbserver-port", required_argument, NULL, 'M' },
|
||||
{ "port-file", required_argument, NULL, 'f' },
|
||||
{ "socket-file", required_argument, NULL, 'f' },
|
||||
{ "server", no_argument, &g_server, 1 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
@ -100,9 +102,9 @@ display_usage (const char *progname, const char *subcommand)
|
|||
}
|
||||
|
||||
static Error
|
||||
save_port_to_file(const uint16_t port, const FileSpec &port_file_spec)
|
||||
save_socket_id_to_file(const std::string &socket_id, const FileSpec &file_spec)
|
||||
{
|
||||
FileSpec temp_file_spec(port_file_spec.GetDirectory().AsCString(), false);
|
||||
FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false);
|
||||
auto error = FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault);
|
||||
if (error.Fail())
|
||||
return Error("Failed to create directory %s: %s", temp_file_spec.GetCString(), error.AsCString());
|
||||
|
@ -119,13 +121,13 @@ save_port_to_file(const uint16_t port, const FileSpec &port_file_spec)
|
|||
std::ofstream temp_file(temp_file_path.c_str(), std::ios::out);
|
||||
if (!temp_file.is_open())
|
||||
return Error("Failed to open temp file %s", temp_file_path.c_str());
|
||||
temp_file << port;
|
||||
temp_file << socket_id;
|
||||
}
|
||||
|
||||
err_code = llvm::sys::fs::rename(temp_file_path.c_str(), port_file_spec.GetPath().c_str());
|
||||
err_code = llvm::sys::fs::rename(temp_file_path.c_str(), file_spec.GetPath().c_str());
|
||||
if (err_code)
|
||||
return Error("Failed to rename file %s to %s: %s",
|
||||
temp_file_path.c_str(), port_file_spec.GetPath().c_str(), err_code.message().c_str());
|
||||
temp_file_path.c_str(), file_spec.GetPath().c_str(), err_code.message().c_str());
|
||||
|
||||
tmp_file_remover.releaseFile();
|
||||
return Error();
|
||||
|
@ -156,7 +158,7 @@ main_platform (int argc, char *argv[])
|
|||
int max_gdbserver_port = 0;
|
||||
uint16_t port_offset = 0;
|
||||
|
||||
FileSpec port_file;
|
||||
FileSpec socket_file;
|
||||
bool show_usage = false;
|
||||
int option_error = 0;
|
||||
int socket_error = -1;
|
||||
|
@ -191,9 +193,9 @@ main_platform (int argc, char *argv[])
|
|||
log_channels = StringRef(optarg);
|
||||
break;
|
||||
|
||||
case 'f': // Port file
|
||||
case 'f': // Socket file
|
||||
if (optarg && optarg[0])
|
||||
port_file.SetFile(optarg, false);
|
||||
socket_file.SetFile(optarg, false);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
|
@ -282,39 +284,38 @@ main_platform (int argc, char *argv[])
|
|||
display_usage(progname, subcommand);
|
||||
exit(option_error);
|
||||
}
|
||||
|
||||
Socket *socket = nullptr;
|
||||
|
||||
const bool children_inherit_listen_socket = false;
|
||||
|
||||
// the test suite makes many connections in parallel, let's not miss any.
|
||||
// The highest this should get reasonably is a function of the number
|
||||
// of target CPUs. For now, let's just use 100
|
||||
// The highest this should get reasonably is a function of the number
|
||||
// of target CPUs. For now, let's just use 100.
|
||||
const int backlog = 100;
|
||||
std::unique_ptr<TCPSocket> listening_socket_up(new TCPSocket(children_inherit_listen_socket, error));
|
||||
|
||||
std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(listen_host_port, children_inherit_listen_socket, error));
|
||||
if (error.Fail())
|
||||
{
|
||||
fprintf(stderr, "failed to create socket: %s", error.AsCString());
|
||||
fprintf(stderr, "failed to create acceptor: %s", error.AsCString());
|
||||
exit(socket_error);
|
||||
}
|
||||
|
||||
error = listening_socket_up->Listen(listen_host_port.c_str(), backlog);
|
||||
error = acceptor_up->Listen(backlog);
|
||||
if (error.Fail())
|
||||
{
|
||||
printf("error: %s\n", error.AsCString());
|
||||
printf("failed to listen: %s\n", error.AsCString());
|
||||
exit(socket_error);
|
||||
}
|
||||
if (port_file)
|
||||
if (socket_file)
|
||||
{
|
||||
error = save_port_to_file(listening_socket_up->GetLocalPortNumber(), port_file);
|
||||
error = save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file);
|
||||
if (error.Fail())
|
||||
{
|
||||
fprintf(stderr, "failed to write port to %s: %s", port_file.GetPath().c_str(), error.AsCString());
|
||||
fprintf(stderr, "failed to write socket id to %s: %s", socket_file.GetPath().c_str(), error.AsCString());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
GDBRemoteCommunicationServerPlatform platform;
|
||||
GDBRemoteCommunicationServerPlatform platform(acceptor_up->GetSocketProtocol());
|
||||
|
||||
if (port_offset > 0)
|
||||
platform.SetPortOffset(port_offset);
|
||||
|
@ -325,8 +326,8 @@ main_platform (int argc, char *argv[])
|
|||
}
|
||||
|
||||
const bool children_inherit_accept_socket = true;
|
||||
socket = nullptr;
|
||||
error = listening_socket_up->Accept(listen_host_port.c_str(), children_inherit_accept_socket, socket);
|
||||
Connection* conn = nullptr;
|
||||
error = acceptor_up->Accept(children_inherit_accept_socket, conn);
|
||||
if (error.Fail())
|
||||
{
|
||||
printf ("error: %s\n", error.AsCString());
|
||||
|
@ -340,8 +341,7 @@ main_platform (int argc, char *argv[])
|
|||
if (fork())
|
||||
{
|
||||
// Parent doesn't need a connection to the lldb client
|
||||
delete socket;
|
||||
socket = nullptr;
|
||||
delete conn;
|
||||
|
||||
// Parent will continue to listen for new connections.
|
||||
continue;
|
||||
|
@ -351,16 +351,16 @@ main_platform (int argc, char *argv[])
|
|||
// Child process will handle the connection and exit.
|
||||
g_server = 0;
|
||||
// Listening socket is owned by parent process.
|
||||
listening_socket_up.release();
|
||||
acceptor_up.release();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not running as a server, this process will not accept
|
||||
// connections while a connection is active.
|
||||
listening_socket_up.reset();
|
||||
acceptor_up.reset();
|
||||
}
|
||||
platform.SetConnection (new ConnectionFileDescriptor(socket));
|
||||
platform.SetConnection (conn);
|
||||
|
||||
if (platform.IsConnected())
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue