Skip to content

Commit

Permalink
Patch 1352 (continued in issue 1329) by Christian Heimes.
Browse files Browse the repository at this point in the history
Before sys.stderr is set to the proper thing, set it to a really simple
file-like object that can print tracebacks using direct file descriptor I/O.
This is handy for debugging.
  • Loading branch information
gvanrossum committed Oct 30, 2007
1 parent 1cd5bd2 commit 826d897
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Include/fileobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *);
*/
PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding;

/* Internal API
The std printer acts as a preliminary sys.stderr until the new io
infrastructure is in place. */
PyAPI_FUNC(PyObject *) PyFile_NewStdPrinter(int);
PyAPI_DATA(PyTypeObject) PyStdPrinter_Type;

#ifdef __cplusplus
}
#endif
Expand Down
118 changes: 118 additions & 0 deletions Objects/fileobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,124 @@ Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
return buf;
}

/* **************************** std printer **************************** */

typedef struct {
PyObject_HEAD
int fd;
} PyStdPrinter_Object;

static PyObject *
stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews)
{
PyStdPrinter_Object *self;

assert(type != NULL && type->tp_alloc != NULL);

self = (PyStdPrinter_Object *) type->tp_alloc(type, 0);
if (self != NULL) {
self->fd = -1;
}

return (PyObject *) self;
}

PyObject *
PyFile_NewStdPrinter(int fd)
{
PyStdPrinter_Object *self;

if (fd != 1 && fd != 2) {
PyErr_BadInternalCall();
return NULL;
}

self = PyObject_New(PyStdPrinter_Object,
&PyStdPrinter_Type);
self->fd = fd;
return (PyObject*)self;
}

PyObject *
stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
{
char *c;
Py_ssize_t n;

if (self->fd < 0) {
PyErr_SetString(PyExc_ValueError,
"I/O operation on closed file");
return NULL;
}

if (!PyArg_ParseTuple(args, "s#", &c, &n)) {
return NULL;
}

Py_BEGIN_ALLOW_THREADS
errno = 0;
n = write(self->fd, c, n);
Py_END_ALLOW_THREADS

if (n < 0) {
if (errno == EAGAIN)
Py_RETURN_NONE;
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}

return PyInt_FromSsize_t(n);
}

static PyMethodDef stdprinter_methods[] = {
{"write", (PyCFunction)stdprinter_write, METH_VARARGS, ""},
{NULL, NULL} /* sentinel */
};

PyTypeObject PyStdPrinter_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"stderrprinter", /* tp_name */
sizeof(PyStdPrinter_Object), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
stdprinter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
stdprinter_new, /* tp_new */
PyObject_Del, /* tp_free */
};


#ifdef __cplusplus
}
#endif
3 changes: 3 additions & 0 deletions Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1595,6 +1595,9 @@ _Py_ReadyTypes(void)

if (PyType_Ready(&PyCode_Type) < 0)
Py_FatalError("Can't initialize 'code'");

if (PyType_Ready(&PyStdPrinter_Type) < 0)
Py_FatalError("Can't initialize StdPrinter");
}


Expand Down
9 changes: 8 additions & 1 deletion Python/pythonrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Py_InitializeEx(int install_sigs)
{
PyInterpreterState *interp;
PyThreadState *tstate;
PyObject *bimod, *sysmod;
PyObject *bimod, *sysmod, *pstderr;
char *p;
#if defined(HAVE_LANGINFO_H) && defined(CODESET)
char *codeset;
Expand Down Expand Up @@ -228,6 +228,13 @@ Py_InitializeEx(int install_sigs)
PyDict_SetItemString(interp->sysdict, "modules",
interp->modules);

/* Set up a preliminary stderr printer until we have enough
infrastructure for the io module in place. */
pstderr = PyFile_NewStdPrinter(fileno(stderr));
if (pstderr == NULL)
Py_FatalError("Py_Initialize: can't set preliminary stderr");
PySys_SetObject("stderr", pstderr);

_PyImport_Init();

/* initialize builtin exceptions */
Expand Down

0 comments on commit 826d897

Please sign in to comment.