summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2010-10-19 03:25:40 +0000
committerGreg Clayton <gclayton@apple.com>2010-10-19 03:25:40 +0000
commit3fcbed6bda344dbf16dd0db8930b28d95bc4b4b4 (patch)
tree13e028c6e8f9439c1edb618d74f297c4068c53d6
parent392f084f46f9b759f9aca3d429f681cb6b32f2e0 (diff)
downloadbcm5719-llvm-3fcbed6bda344dbf16dd0db8930b28d95bc4b4b4.tar.gz
bcm5719-llvm-3fcbed6bda344dbf16dd0db8930b28d95bc4b4b4.zip
Stop the driver from handling SIGPIPE in case we communicate with stale
sockets so the driver doesn't just crash. Added support for connecting to named sockets (unix IPC sockets) in ConnectionFileDescriptor. Modified the Host::LaunchInNewTerminal() for MacOSX to return the process ID of the inferior process instead of the process ID of the Terminal.app. This was done by modifying the "darwin-debug" executable to connect to lldb through a named unix socket which is passed down as an argument. This allows a quick handshake between "lldb" and "darwin-debug" so we can get the process ID of the inferior and then attach by process ID and avoid attaching to the inferior by process name since there could be more than one process with that name. This still has possible race conditions, those will be fixed in the near future. This fixes the SIGPIPE issues that were sometimes being seen when task_for_pid was failing. llvm-svn: 116792
-rw-r--r--lldb/include/lldb/Core/ConnectionFileDescriptor.h3
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp29
-rw-r--r--lldb/source/Core/ConnectionFileDescriptor.cpp53
-rw-r--r--lldb/source/Host/macosx/Host.mm41
-rw-r--r--lldb/source/Target/Process.cpp12
-rw-r--r--lldb/tools/darwin-debug/darwin-debug.cpp58
-rw-r--r--lldb/tools/driver/Driver.cpp1
7 files changed, 158 insertions, 39 deletions
diff --git a/lldb/include/lldb/Core/ConnectionFileDescriptor.h b/lldb/include/lldb/Core/ConnectionFileDescriptor.h
index 53a3997eab7..b679892d203 100644
--- a/lldb/include/lldb/Core/ConnectionFileDescriptor.h
+++ b/lldb/include/lldb/Core/ConnectionFileDescriptor.h
@@ -56,6 +56,9 @@ protected:
SocketConnect (const char *host_and_port, Error *error_ptr);
lldb::ConnectionStatus
+ NamedSocketAccept (const char *socket_name, Error *error_ptr);
+
+ lldb::ConnectionStatus
Close (int& fd, Error *error);
int m_fd; // Socket we use to communicate once conn established
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index ea3bd95dffc..82d664b0a16 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -216,29 +216,14 @@ public:
if (m_options.in_new_tty)
{
- lldb::pid_t terminal_pid = Host::LaunchInNewTerminal (inferior_argv,
- inferior_envp,
- &exe_module->GetArchitecture(),
- true,
- process->GetDisableASLR());
+ lldb::pid_t pid = Host::LaunchInNewTerminal (inferior_argv,
+ inferior_envp,
+ &exe_module->GetArchitecture(),
+ true,
+ process->GetDisableASLR());
- // Let the app get launched and stopped...
- const char *process_name = exe_module->GetFileSpec().GetFilename().AsCString("<invalid>");
-
- if (terminal_pid == LLDB_INVALID_PROCESS_ID)
- {
- error.SetErrorStringWithFormat ("failed to launch '%s' in new terminal", process_name);
- }
- else
- {
- for (int i=0; i<20; i++)
- {
- usleep (250000);
- error = process->Attach (process_name, false);
- if (error.Success())
- break;
- }
- }
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ error = process->Attach (pid);
}
else
{
diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp
index 292bc746b0b..dc190a1b781 100644
--- a/lldb/source/Core/ConnectionFileDescriptor.cpp
+++ b/lldb/source/Core/ConnectionFileDescriptor.cpp
@@ -18,6 +18,7 @@
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <sys/un.h>
#include <string.h>
#include <stdlib.h>
@@ -85,6 +86,11 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
unsigned long listen_port = ::strtoul(s + strlen("listen://"), &end, 0);
return SocketListen (listen_port, error_ptr);
}
+ else if (strstr(s, "unix-accept://"))
+ {
+ // unix://SOCKNAME
+ return NamedSocketAccept (s + strlen("unix-accept://"), error_ptr);
+ }
else if (strstr(s, "connect://"))
{
return SocketConnect (s + strlen("connect://"), error_ptr);
@@ -400,6 +406,53 @@ ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
}
ConnectionStatus
+ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr)
+{
+ ConnectionStatus result = eConnectionStatusError;
+ struct sockaddr_un saddr_un;
+
+ m_is_socket = true;
+
+ int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (listen_socket == -1)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorToErrno();
+ return eConnectionStatusError;
+ }
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+
+ if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
+ {
+ if (::listen (listen_socket, 5) == 0)
+ {
+ m_fd = ::accept (listen_socket, NULL, 0);
+ if (m_fd > 0)
+ {
+ m_should_close_fd = true;
+
+ if (error_ptr)
+ error_ptr->Clear();
+ result = eConnectionStatusSuccess;
+ }
+ }
+ }
+
+ if (result != eConnectionStatusSuccess)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorToErrno();
+ }
+ // We are done with the listen port
+ Close (listen_socket, NULL);
+ return result;
+}
+
+ConnectionStatus
ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr)
{
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm
index c7c6e496747..8dec00b4867 100644
--- a/lldb/source/Host/macosx/Host.mm
+++ b/lldb/source/Host/macosx/Host.mm
@@ -13,6 +13,8 @@
#include <sys/stat.h>
#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/FileSpec.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamFile.h"
@@ -176,6 +178,8 @@ Host::LaunchInNewTerminal
FileSpec program (argv[0]);
+ std::string unix_socket_name;
+
char temp_file_path[PATH_MAX];
const char *tmpdir = ::getenv ("TMPDIR");
if (tmpdir == NULL)
@@ -185,6 +189,8 @@ Host::LaunchInNewTerminal
if (::mktemp (temp_file_path) == NULL)
return LLDB_INVALID_PROCESS_ID;
+ unix_socket_name.assign (temp_file_path);
+
::strncat (temp_file_path, ".command", sizeof (temp_file_path));
StreamFile command_file (temp_file_path, "w");
@@ -201,6 +207,8 @@ Host::LaunchInNewTerminal
darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
command_file.Printf("\"%s\" ", launcher_path);
+ command_file.Printf("--unix-socket=%s ", unix_socket_name.c_str());
+
if (arch_spec && arch_spec->IsValid())
{
command_file.Printf("--arch=%s ", arch_spec->AsCString());
@@ -253,7 +261,7 @@ Host::LaunchInNewTerminal
CFCReleaser<CFURLRef> command_file_url (::CFURLCreateFromFileSystemRepresentation (NULL,
(const UInt8 *)temp_file_path,
- strlen (temp_file_path),
+ strlen(temp_file_path),
false));
CFCMutableArray urls;
@@ -263,14 +271,33 @@ Host::LaunchInNewTerminal
// for us to attach.
urls.AppendValue(command_file_url.get());
- ProcessSerialNumber psn;
- error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1);
- if (error != noErr)
- return LLDB_INVALID_PROCESS_ID;
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
- ::pid_t pid = LLDB_INVALID_PROCESS_ID;
- error = ::GetProcessPID(&psn, &pid);
+ Error lldb_error;
+ // Sleep and wait a bit for debugserver to start to listen...
+ ConnectionFileDescriptor file_conn;
+ char connect_url[128];
+ ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
+
+ ProcessSerialNumber psn;
+ error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1);
+ if (error == noErr)
+ {
+ if (file_conn.Connect(connect_url, &lldb_error) == eConnectionStatusSuccess)
+ {
+ char pid_str[256];
+ ::bzero (pid_str, sizeof(pid_str));
+ ConnectionStatus status;
+ const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
+ if (pid_str_len > 0)
+ {
+ pid = atoi (pid_str);
+ // Sleep for a bit to allow the process to exec and stop at the entry point...
+ sleep(1);
+ }
+ }
+ }
return pid;
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index e4a5bdb682c..7d481a37c33 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -243,10 +243,10 @@ Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp)
log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
StateType state = eStateInvalid;
- if (m_listener.WaitForEventForBroadcasterWithType(timeout,
- this,
- eBroadcastBitStateChanged,
- event_sp))
+ if (m_listener.WaitForEventForBroadcasterWithType (timeout,
+ this,
+ eBroadcastBitStateChanged,
+ event_sp))
state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
if (log)
@@ -266,8 +266,8 @@ Process::PeekAtStateChangedEvents ()
log->Printf ("Process::%s...", __FUNCTION__);
Event *event_ptr;
- event_ptr = m_listener.PeekAtNextEventForBroadcasterWithType(this,
- eBroadcastBitStateChanged);
+ event_ptr = m_listener.PeekAtNextEventForBroadcasterWithType (this,
+ eBroadcastBitStateChanged);
if (log)
{
if (event_ptr)
diff --git a/lldb/tools/darwin-debug/darwin-debug.cpp b/lldb/tools/darwin-debug/darwin-debug.cpp
index a894806f64c..a38bfc249d4 100644
--- a/lldb/tools/darwin-debug/darwin-debug.cpp
+++ b/lldb/tools/darwin-debug/darwin-debug.cpp
@@ -30,6 +30,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <string>
#ifndef _POSIX_SPAWN_DISABLE_ASLR
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
@@ -44,6 +49,7 @@ static struct option g_long_options[] =
{ "no-env", no_argument, NULL, 'e' },
{ "help", no_argument, NULL, 'h' },
{ "setsid", no_argument, NULL, 's' },
+ { "unix-socket", required_argument, NULL, 'u' },
{ NULL, 0, NULL, 0 }
};
@@ -56,7 +62,7 @@ usage()
" for debugging.\n"
"\n"
"SYNOPSIS\n"
-" darwin-debug [--arch=<ARCH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
+" darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
"\n"
"DESCRIPTION\n"
" darwin-debug will exec itself into a child process <PROGRAM> that is\n"
@@ -65,7 +71,9 @@ usage()
" stop at the program entry point. Any program arguments <PROGRAM-ARG> are\n"
" passed on to the exec as the arguments for the new process. The current\n"
" environment will be passed to the new process unless the \"--no-env\"\n"
-" option is used.\n"
+" option is used. A unix socket must be supplied using the\n"
+" --unix-socket=<SOCKET> option so the calling program can handshake with\n"
+" this process and get its process id.\n"
"\n"
"EXAMPLE\n"
" darwin-debug --arch=i386 -- /bin/ls -al /tmp\n"
@@ -148,7 +156,8 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
char ch;
int disable_aslr = 0; // By default we disable ASLR
int pass_env = 1;
- while ((ch = getopt_long(argc, argv, "a:dfh?", g_long_options, NULL)) != -1)
+ std::string unix_socket_name;
+ while ((ch = getopt_long(argc, argv, "a:dehsu:?", g_long_options, NULL)) != -1)
{
switch (ch)
{
@@ -186,6 +195,10 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
::setsid();
break;
+ case 'u':
+ unix_socket_name.assign (optarg);
+ break;
+
case 'h':
case '?':
default:
@@ -196,7 +209,7 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
argc -= optind;
argv += optind;
- if (show_usage || argc <= 0)
+ if (show_usage || argc <= 0 || unix_socket_name.empty())
usage();
#if defined (DEBUG_LLDB_LAUNCHER)
@@ -205,6 +218,43 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
printf ("argv[%u] = '%s'\n", i, argv[i]);
#endif
+ // Open the socket that was passed in as an argument
+ struct sockaddr_un saddr_un;
+ int s = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0)
+ {
+ perror("error: socket (AF_UNIX, SOCK_STREAM, 0)");
+ exit(1);
+ }
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, unix_socket_name.c_str(), sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+
+ if (::connect (s, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+ {
+ perror("error: connect (socket, &saddr_un, saddr_un_len)");
+ exit(1);
+ }
+
+ // We were able to connect to the socket, now write our PID so whomever
+ // launched us will know this process's ID
+ char pid_str[64];
+ const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%i", ::getpid());
+ const int bytes_sent = ::send (s, pid_str, pid_str_len, 0);
+
+ if (pid_str_len != bytes_sent)
+ {
+ perror("error: send (s, pid_str, pid_str_len, 0)");
+ exit (1);
+ }
+
+ // We are done with the socket
+ close (s);
+
+ // Now we posix spawn to exec this process into the inferior that we want
+ // to debug.
posix_spawn_for_debug (argv,
pass_env ? envp : NULL,
cpu_type,
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index 9887e35850a..8d9abdd9eec 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -1377,6 +1377,7 @@ main (int argc, char const *argv[])
SBHostOS::ThreadCreated ("[main]");
+ signal (SIGPIPE, SIG_IGN);
signal (SIGWINCH, sigwinch_handler);
// Create a scope for driver so that the driver object will destroy itself
OpenPOWER on IntegriCloud