Implement -w flag to process launch (allow launching inferior process in different working directory) on Linux/FreeBSD

- fixes test case TestProcessLaunch

llvm-svn: 171854
This commit is contained in:
Daniel Malea 2013-01-08 14:49:22 +00:00
parent 7daa1a2201
commit 6217d2ae37
6 changed files with 54 additions and 10 deletions

View File

@ -627,14 +627,16 @@ ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
char const **envp,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path)
const char *stderr_path,
const char *working_dir)
: OperationArgs(monitor),
m_module(module),
m_argv(argv),
m_envp(envp),
m_stdin_path(stdin_path),
m_stdout_path(stdout_path),
m_stderr_path(stderr_path) { }
m_stderr_path(stderr_path),
m_working_dir(working_dir) { }
ProcessMonitor::LaunchArgs::~LaunchArgs()
{ }
@ -665,6 +667,7 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_dir,
lldb_private::Error &error)
: m_process(static_cast<ProcessFreeBSD *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
@ -678,7 +681,7 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
std::auto_ptr<LaunchArgs> args;
args.reset(new LaunchArgs(this, module, argv, envp,
stdin_path, stdout_path, stderr_path));
stdin_path, stdout_path, stderr_path, working_dir));
// Server/client descriptors.
@ -839,6 +842,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
const char *stdin_path = args->m_stdin_path;
const char *stdout_path = args->m_stdout_path;
const char *stderr_path = args->m_stderr_path;
const char *working_dir = args->m_working_dir;
lldb::pid_t pid;
lldb::ThreadSP inferior;
@ -853,6 +857,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
eDupStdinFailed,
eDupStdoutFailed,
eDupStderrFailed,
eChdirFailed,
eExecFailed
};
@ -887,6 +892,11 @@ ProcessMonitor::Launch(LaunchArgs *args)
if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
exit(eDupStderrFailed);
// Change working directory
if (working_dir != NULL && working_dir[0])
if (0 != ::chdir(working_dir))
exit(eChdirFailed);
// Execute. We should never return.
execve(argv[0],
const_cast<char *const *>(argv),
@ -920,6 +930,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
case eDupStderrFailed:
args->m_error.SetErrorString("Child open stderr failed.");
break;
case eChdirFailed:
args->m_error.SetErrorString("Child failed to set working directory.");
break;
case eExecFailed:
args->m_error.SetErrorString("Child exec failed.");
break;

View File

@ -54,6 +54,7 @@ public:
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_dir,
lldb_private::Error &error);
ProcessMonitor(ProcessPOSIX *process,
@ -210,7 +211,8 @@ private:
char const **envp,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path);
const char *stderr_path,
const char *working_dir);
~LaunchArgs();
@ -220,6 +222,7 @@ private:
const char *m_stdin_path; // Redirect stdin or NULL.
const char *m_stdout_path; // Redirect stdout or NULL.
const char *m_stderr_path; // Redirect stderr or NULL.
const char *m_working_dir; // Working directory or NULL.
};
void

View File

@ -780,14 +780,16 @@ ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
char const **envp,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path)
const char *stderr_path,
const char *working_dir)
: OperationArgs(monitor),
m_module(module),
m_argv(argv),
m_envp(envp),
m_stdin_path(stdin_path),
m_stdout_path(stdout_path),
m_stderr_path(stderr_path) { }
m_stderr_path(stderr_path),
m_working_dir(working_dir) { }
ProcessMonitor::LaunchArgs::~LaunchArgs()
{ }
@ -818,6 +820,7 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_dir,
lldb_private::Error &error)
: m_process(static_cast<ProcessLinux *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
@ -830,7 +833,7 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
std::auto_ptr<LaunchArgs> args;
args.reset(new LaunchArgs(this, module, argv, envp,
stdin_path, stdout_path, stderr_path));
stdin_path, stdout_path, stderr_path, working_dir));
// Server/client descriptors.
if (!EnableIPC())
@ -976,6 +979,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
const char *stdin_path = args->m_stdin_path;
const char *stdout_path = args->m_stdout_path;
const char *stderr_path = args->m_stderr_path;
const char *working_dir = args->m_working_dir;
lldb_utility::PseudoTerminal terminal;
const size_t err_len = 1024;
@ -1010,6 +1014,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
eDupStdinFailed,
eDupStdoutFailed,
eDupStderrFailed,
eChdirFailed,
eExecFailed
};
@ -1042,6 +1047,11 @@ ProcessMonitor::Launch(LaunchArgs *args)
if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
exit(eDupStderrFailed);
// Change working directory
if (working_dir != NULL && working_dir[0])
if (0 != ::chdir(working_dir))
exit(eChdirFailed);
// Execute. We should never return.
execve(argv[0],
const_cast<char *const *>(argv),
@ -1075,6 +1085,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
case eDupStderrFailed:
args->m_error.SetErrorString("Child open stderr failed.");
break;
case eChdirFailed:
args->m_error.SetErrorString("Child failed to set working directory.");
break;
case eExecFailed:
args->m_error.SetErrorString("Child exec failed.");
break;

View File

@ -56,6 +56,7 @@ public:
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_dir,
lldb_private::Error &error);
ProcessMonitor(ProcessPOSIX *process,
@ -200,7 +201,8 @@ private:
char const **envp,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path);
const char *stderr_path,
const char *working_dir);
~LaunchArgs();
@ -210,6 +212,7 @@ private:
const char *m_stdin_path; // Redirect stdin or NULL.
const char *m_stdout_path; // Redirect stdout or NULL.
const char *m_stderr_path; // Redirect stderr or NULL.
const char *m_working_dir; // Working directory or NULL.
};
void

View File

@ -17,6 +17,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
@ -162,6 +163,16 @@ ProcessPOSIX::DoLaunch (Module *module,
Error error;
assert(m_monitor == NULL);
const char* working_dir = launch_info.GetWorkingDirectory();
if (working_dir) {
FileSpec WorkingDir(working_dir, true);
if (!WorkingDir || WorkingDir.GetFileType() != FileSpec::eFileTypeDirectory)
{
error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
return error;
}
}
SetPrivateState(eStateLaunching);
const lldb_private::ProcessLaunchInfo::FileAction *file_action;
@ -170,7 +181,7 @@ ProcessPOSIX::DoLaunch (Module *module,
const char *stdin_path = NULL;
const char *stdout_path = NULL;
const char *stderr_path = NULL;
file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
stdin_path = GetFilePath(file_action, stdin_path);
@ -187,6 +198,7 @@ ProcessPOSIX::DoLaunch (Module *module,
stdin_path,
stdout_path,
stderr_path,
working_dir,
error);
m_module = module;

View File

@ -152,7 +152,7 @@ class ProcessLaunchTestCase(TestBase):
err_file_path)
self.expect(launch_command, error=True,
startstr = "error: No such file or directory: %sz" % my_working_dir_path)
patterns = ["error:.* No such file or directory: %sz" % my_working_dir_path])
# Really launch the process
launch_command = "process launch -w %s -o %s -e %s" % (my_working_dir_path,