void SetOutputFileHandle(FILE *f, bool transfer_ownership);
void SetErrorFileHandle(FILE *f, bool transfer_ownership);
-
- void Flush();
FILE *GetInputFileHandle();
void SetOutputFileHandle(FILE *fh, bool tranfer_ownership);
void SetErrorFileHandle(FILE *fh, bool tranfer_ownership);
-
- void Flush();
void SaveInputTerminalState();
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.
///
LazyBool m_is_interactive;
LazyBool m_is_real_terminal;
LazyBool m_supports_colors;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(File);
};
} // namespace lldb_private
void
SetErrorFileHandle (FILE *f, bool transfer_ownership);
- void
- Flush ();
-
FILE *
GetInputFileHandle ();
m_opaque_sp->SetInputFileHandle(fh, transfer_ownership);
}
-void SBDebugger::Flush() {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
-
- if (log)
- log->Printf(
- "SBDebugger(%p)::Flush ()",
- 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));
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) {
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();
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
-#include <assert.h>
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
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),
#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"
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`.
return false;
return true;
+#endif
}
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;
}
.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;
- }
+ file.Close();
+ // 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
}
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.
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);
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;