Ahhhh roll back that commit, I didn't see that Lawrence had filed

a separate phabracator with the revised change.  This was his
first atttempt which broke on the bots the second time too.

llvm-svn: 317181
This commit is contained in:
Jason Molenda 2017-11-02 02:33:59 +00:00
parent c139a402b2
commit 9e27b70a07
10 changed files with 21 additions and 308 deletions

View File

@ -78,9 +78,6 @@ public:
void SetOutputFileHandle(FILE *f, bool transfer_ownership);
void SetErrorFileHandle(FILE *f, bool transfer_ownership);
// Force a flush of the OutputFileHandle and ErrorFileHandle.
void FlushDebuggerOutputHandles();
FILE *GetInputFileHandle();

View File

@ -139,8 +139,6 @@ public:
void SetOutputFileHandle(FILE *fh, bool tranfer_ownership);
void SetErrorFileHandle(FILE *fh, bool tranfer_ownership);
void Flush();
void SaveInputTerminalState();

View File

@ -62,17 +62,6 @@ public:
m_is_interactive(eLazyBoolCalculate),
m_is_real_terminal(eLazyBoolCalculate) {}
File(File &&rhs);
File& operator= (File &&rhs);
void Swap(File &other);
File(void *cookie,
int (*readfn)(void *, char *, int),
int (*writefn)(void *, const char *, int),
int (*closefn)(void *));
//------------------------------------------------------------------
/// Constructor with path.
///
@ -490,6 +479,9 @@ protected:
LazyBool m_is_interactive;
LazyBool m_is_real_terminal;
LazyBool m_supports_colors;
private:
DISALLOW_COPY_AND_ASSIGN(File);
};
} // namespace lldb_private

View File

@ -171,14 +171,6 @@ public:
void
SetErrorFileHandle (FILE *f, bool transfer_ownership);
%feature("docstring",
"Flush the Debugger's Output/Error file handles.
For instance, this is needed by a repl implementation on top of
the SB API, where fine grained control of output timing was needed."
) FlushDebuggerOutputHandles;
void
FlushDebuggerOutputHandles ();
FILE *
GetInputFileHandle ();

View File

@ -270,18 +270,6 @@ void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
m_opaque_sp->SetInputFileHandle(fh, transfer_ownership);
}
void SBDebugger::FlushDebuggerOutputHandles() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
if (log)
log->Printf(
"SBDebugger(%p)::FlushDebuggerOutputHandles ()",
static_cast<void *>(m_opaque_sp.get()));
if (m_opaque_sp)
m_opaque_sp->Flush();
}
void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

View File

@ -680,15 +680,6 @@ void Debugger::Destroy(DebuggerSP &debugger_sp) {
if (!debugger_sp)
return;
/*
* FILE* get flushed on process exit. If those FILEs need to call into python
* to flush, we can't have them flushing after python is already torn down.
* That would result in a segfault. We are still relying on the python script
* to tear down the debugger before it exits.
*/
debugger_sp->m_output_file_sp->Flush();
debugger_sp->m_error_file_sp->Flush();
debugger_sp->Clear();
if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
@ -905,11 +896,6 @@ void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
err_file.SetStream(stderr, false);
}
void Debugger::Flush() {
m_output_file_sp->Flush();
m_error_file_sp->Flush();
}
void Debugger::SaveInputTerminalState() {
if (m_input_file_sp) {
File &in_file = m_input_file_sp->GetFile();

View File

@ -14,7 +14,6 @@
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
@ -72,129 +71,6 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) {
int File::kInvalidDescriptor = -1;
FILE *File::kInvalidStream = NULL;
File::File(File &&rhs)
: IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
m_stream(kInvalidStream), m_options(), m_own_stream(false),
m_is_interactive(eLazyBoolCalculate),
m_is_real_terminal(eLazyBoolCalculate),
m_supports_colors(eLazyBoolCalculate)
{
Swap(rhs);
}
File& File::operator= (File &&rhs)
{
Close();
Swap(rhs);
return *this;
}
void File::Swap(File &rhs)
{
std::swap(m_descriptor, rhs.m_descriptor);
std::swap(m_stream, rhs.m_stream);
std::swap(m_own_stream, rhs.m_own_stream);
std::swap(m_options, rhs.m_options);
std::swap(m_is_interactive, rhs.m_is_interactive);
std::swap(m_is_real_terminal, rhs.m_is_real_terminal);
std::swap(m_supports_colors, rhs.m_supports_colors);
}
#if defined(__linux__)
struct context {
void *cookie;
int (*readfn)(void *, char *, int);
int (*writefn)(void *, const char *, int);
int (*closefn)(void *);
};
static ssize_t
write_wrapper(void *c, const char *buf, size_t size)
{
auto ctx = (struct context *)c;
if (size > INT_MAX) {
size = INT_MAX;
}
ssize_t wrote = ctx->writefn(ctx->cookie, buf, (int)size);
assert(wrote < 0 || (size_t)wrote <= size);
if (wrote < 0) {
return -1;
} else {
return (int)wrote;
}
}
static ssize_t
read_wrapper(void *c, char *buf, size_t size)
{
auto ctx = (struct context *)c;
if (size > INT_MAX) {
size = INT_MAX;
}
ssize_t read = ctx->writefn(ctx->cookie, buf, (int)size);
assert(read < 0 || (size_t)read <= size);
if (read < 0) {
return -1;
} else {
return (int)read;
}
}
static int
close_wrapper(void *c)
{
auto ctx = (struct context *)c;
int ret = ctx->closefn(ctx->cookie);
delete ctx;
return ret;
}
#endif
File::File(void *cookie,
int (*readfn)(void *, char *, int),
int (*writefn)(void *, const char *, int),
int (*closefn)(void *))
: IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
m_stream(kInvalidStream), m_options(), m_own_stream(false),
m_is_interactive(eLazyBoolCalculate),
m_is_real_terminal(eLazyBoolCalculate),
m_supports_colors(eLazyBoolCalculate)
{
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
m_stream = funopen(cookie, readfn, writefn, NULL, closefn);
#elif defined(__linux__)
cookie_io_functions_t io_funcs = {};
io_funcs.read = read_wrapper;
io_funcs.write = write_wrapper;
io_funcs.close = close_wrapper;
const char *mode = NULL;
if (readfn && writefn) {
mode = "r+";
} else if (readfn) {
mode = "r";
} else if (writefn) {
mode = "w";
}
if (mode) {
struct context *ctx = new context;
ctx->readfn = readfn;
ctx->writefn = writefn;
ctx->closefn = closefn;
ctx->cookie = cookie;
m_stream = fopencookie(ctx, mode, io_funcs);
if (!m_stream) {
delete ctx;
}
}
#endif
if (m_stream) {
m_own_stream = true;
}
}
File::File(const char *path, uint32_t options, uint32_t permissions)
: IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
m_stream(kInvalidStream), m_options(), m_own_stream(false),

View File

@ -17,7 +17,6 @@
#include "PythonDataObjects.h"
#include "ScriptInterpreterPython.h"
#include "lldb/Utility/Log.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
@ -960,11 +959,8 @@ PythonFile::~PythonFile() {}
bool PythonFile::Check(PyObject *py_obj) {
#if PY_MAJOR_VERSION < 3
bool is_ordinary_file = PyFile_Check(py_obj);
if (is_ordinary_file) {
return true;
}
#endif
return PyFile_Check(py_obj);
#else
// In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
// first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
// over `io.open()`, which returns some object derived from `io.IOBase`.
@ -985,6 +981,7 @@ bool PythonFile::Check(PyObject *py_obj) {
return false;
return true;
#endif
}
void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
@ -992,7 +989,7 @@ void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
// `py_obj` it still gets decremented if necessary.
PythonObject result(type, py_obj);
if (py_obj == NULL || !PythonFile::Check(py_obj)) {
if (!PythonFile::Check(py_obj)) {
PythonObject::Reset();
return;
}
@ -1037,131 +1034,17 @@ uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) {
.Default(0);
}
static void
log_exception(const char *fmt, PyObject *obj)
{
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
if (!log) {
return;
}
const char *classname = "unknown class";
PyObject *pyclass = PyObject_Type(obj);
if (pyclass) {
PyObject *s = PyObject_GetAttrString(pyclass, "__name__");
if (s) {
classname = PyString_AsString(s);
Py_XDECREF(s);
}
Py_XDECREF(pyclass);
}
const char *error = "unknown error";
PyObject *exception, *v, *tb;
PyErr_Fetch(&exception, &v, &tb);
if (exception) {
PyErr_NormalizeException(&exception, &v, &tb);
}
PyObject *string = NULL;
if (v) {
string = PyObject_Str(v);
}
error = PyString_AsString(string);
log->Printf(fmt, classname, error);
Py_XDECREF(exception);
Py_XDECREF(v);
Py_XDECREF(tb);
Py_XDECREF(string);
}
static int readfn(void *ctx, char *buffer, int n)
{
auto state = PyGILState_Ensure();
auto *file = (PyObject *) ctx;
int result = -1;
auto pybuffer = PyBuffer_FromMemory(buffer, n);
PyObject *pyresult = NULL;
if (!pybuffer) {
goto fail;
}
pyresult = PyEval_CallMethod(file, "read", "(i)", n);
if (pyresult == NULL || !PyInt_Check(pyresult)) {
log_exception("read from python %s failed: %s", file);
goto fail;
}
result = _PyInt_AsInt(pyresult);
fail:
Py_XDECREF(pybuffer);
Py_XDECREF(pyresult);
PyGILState_Release(state);
return result;
}
static int writefn(void *ctx, const char *buffer, int n)
{
auto state = PyGILState_Ensure();
auto *file = (PyObject *) ctx;
int result = -1;
auto pyresult = PyEval_CallMethod(file, "write", "(s#)", buffer, n);
if (pyresult == NULL || !PyInt_Check(pyresult)) {
log_exception("write to python %s failed: %s", file);
goto fail;
}
result = _PyInt_AsInt(pyresult);
fail:
Py_XDECREF(pyresult);
PyGILState_Release(state);
return result;
}
static int closefn(void *ctx) {
auto *file = (PyObject *) ctx;
auto state = PyGILState_Ensure();
Py_XDECREF(file);
PyGILState_Release(state);
return 0;
}
bool PythonFile::GetUnderlyingFile(File &file) const {
if (!IsValid())
return false;
file.Close();
int fd = PyObject_AsFileDescriptor(m_py_obj);
if (fd >= 0) {
// We don't own the file descriptor returned by this function, make sure the
// File object knows about that.
file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
return file.IsValid();
}
PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
PythonDictionary io_dict(PyRefType::Borrowed,
PyModule_GetDict(io_module.get()));
PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
PythonObject object_type(PyRefType::Owned, PyObject_Type(m_py_obj));
if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
return false;
PyObject *r = PyEval_CallMethod(m_py_obj, "readable", "()");
bool readable = PyObject_IsTrue(r);
r = PyEval_CallMethod(m_py_obj, "writable", "()");
bool writable = PyObject_IsTrue(r);
Py_XINCREF(m_py_obj);
file = File(m_py_obj, readable ? readfn : NULL, writable ? writefn : NULL, closefn);
if (!file.IsValid()) {
closefn(m_py_obj);
return false;
} else {
return true;
}
// We don't own the file descriptor returned by this function, make sure the
// File object knows about that.
file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
return file.IsValid();
}
#endif

View File

@ -504,7 +504,7 @@ void ScriptInterpreterPython::LeaveSession() {
}
bool ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name,
PythonObject &save_file,
PythonFile &save_file,
const char *mode) {
if (file.IsValid()) {
// Flush the file before giving it to python to avoid interleaved output.
@ -512,7 +512,8 @@ bool ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name,
PythonDictionary &sys_module_dict = GetSysModuleDictionary();
save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
save_file = sys_module_dict.GetItemForKey(PythonString(py_name))
.AsType<PythonFile>();
PythonFile new_file(file, mode);
sys_module_dict.SetItemForKey(PythonString(py_name), new_file);

View File

@ -541,12 +541,12 @@ protected:
bool GetEmbeddedInterpreterModuleObjects();
bool SetStdHandle(File &file, const char *py_name, PythonObject &save_file,
bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file,
const char *mode);
PythonObject m_saved_stdin;
PythonObject m_saved_stdout;
PythonObject m_saved_stderr;
PythonFile m_saved_stdin;
PythonFile m_saved_stdout;
PythonFile m_saved_stderr;
PythonObject m_main_module;
PythonObject m_lldb_module;
PythonDictionary m_session_dict;