Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 826d897

Browse files
committed
Patch 1352 (continued in issue 1329) by Christian Heimes.
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.
1 parent 1cd5bd2 commit 826d897

4 files changed

Lines changed: 136 additions & 1 deletion

File tree

Include/fileobject.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *);
2121
*/
2222
PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding;
2323

24+
/* Internal API
25+
26+
The std printer acts as a preliminary sys.stderr until the new io
27+
infrastructure is in place. */
28+
PyAPI_FUNC(PyObject *) PyFile_NewStdPrinter(int);
29+
PyAPI_DATA(PyTypeObject) PyStdPrinter_Type;
30+
2431
#ifdef __cplusplus
2532
}
2633
#endif

Objects/fileobject.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,124 @@ Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
325325
return buf;
326326
}
327327

328+
/* **************************** std printer **************************** */
329+
330+
typedef struct {
331+
PyObject_HEAD
332+
int fd;
333+
} PyStdPrinter_Object;
334+
335+
static PyObject *
336+
stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews)
337+
{
338+
PyStdPrinter_Object *self;
339+
340+
assert(type != NULL && type->tp_alloc != NULL);
341+
342+
self = (PyStdPrinter_Object *) type->tp_alloc(type, 0);
343+
if (self != NULL) {
344+
self->fd = -1;
345+
}
346+
347+
return (PyObject *) self;
348+
}
349+
350+
PyObject *
351+
PyFile_NewStdPrinter(int fd)
352+
{
353+
PyStdPrinter_Object *self;
354+
355+
if (fd != 1 && fd != 2) {
356+
PyErr_BadInternalCall();
357+
return NULL;
358+
}
359+
360+
self = PyObject_New(PyStdPrinter_Object,
361+
&PyStdPrinter_Type);
362+
self->fd = fd;
363+
return (PyObject*)self;
364+
}
365+
366+
PyObject *
367+
stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
368+
{
369+
char *c;
370+
Py_ssize_t n;
371+
372+
if (self->fd < 0) {
373+
PyErr_SetString(PyExc_ValueError,
374+
"I/O operation on closed file");
375+
return NULL;
376+
}
377+
378+
if (!PyArg_ParseTuple(args, "s#", &c, &n)) {
379+
return NULL;
380+
}
381+
382+
Py_BEGIN_ALLOW_THREADS
383+
errno = 0;
384+
n = write(self->fd, c, n);
385+
Py_END_ALLOW_THREADS
386+
387+
if (n < 0) {
388+
if (errno == EAGAIN)
389+
Py_RETURN_NONE;
390+
PyErr_SetFromErrno(PyExc_IOError);
391+
return NULL;
392+
}
393+
394+
return PyInt_FromSsize_t(n);
395+
}
396+
397+
static PyMethodDef stdprinter_methods[] = {
398+
{"write", (PyCFunction)stdprinter_write, METH_VARARGS, ""},
399+
{NULL, NULL} /* sentinel */
400+
};
401+
402+
PyTypeObject PyStdPrinter_Type = {
403+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
404+
"stderrprinter", /* tp_name */
405+
sizeof(PyStdPrinter_Object), /* tp_basicsize */
406+
0, /* tp_itemsize */
407+
/* methods */
408+
0, /* tp_dealloc */
409+
0, /* tp_print */
410+
0, /* tp_getattr */
411+
0, /* tp_setattr */
412+
0, /* tp_compare */
413+
0, /* tp_repr */
414+
0, /* tp_as_number */
415+
0, /* tp_as_sequence */
416+
0, /* tp_as_mapping */
417+
0, /* tp_hash */
418+
0, /* tp_call */
419+
0, /* tp_str */
420+
PyObject_GenericGetAttr, /* tp_getattro */
421+
0, /* tp_setattro */
422+
0, /* tp_as_buffer */
423+
Py_TPFLAGS_DEFAULT, /* tp_flags */
424+
0, /* tp_doc */
425+
0, /* tp_traverse */
426+
0, /* tp_clear */
427+
0, /* tp_richcompare */
428+
0, /* tp_weaklistoffset */
429+
0, /* tp_iter */
430+
0, /* tp_iternext */
431+
stdprinter_methods, /* tp_methods */
432+
0, /* tp_members */
433+
0, /* tp_getset */
434+
0, /* tp_base */
435+
0, /* tp_dict */
436+
0, /* tp_descr_get */
437+
0, /* tp_descr_set */
438+
0, /* tp_dictoffset */
439+
0, /* tp_init */
440+
PyType_GenericAlloc, /* tp_alloc */
441+
stdprinter_new, /* tp_new */
442+
PyObject_Del, /* tp_free */
443+
};
444+
445+
328446
#ifdef __cplusplus
329447
}
330448
#endif

Objects/object.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,9 @@ _Py_ReadyTypes(void)
15951595

15961596
if (PyType_Ready(&PyCode_Type) < 0)
15971597
Py_FatalError("Can't initialize 'code'");
1598+
1599+
if (PyType_Ready(&PyStdPrinter_Type) < 0)
1600+
Py_FatalError("Can't initialize StdPrinter");
15981601
}
15991602

16001603

Python/pythonrun.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Py_InitializeEx(int install_sigs)
151151
{
152152
PyInterpreterState *interp;
153153
PyThreadState *tstate;
154-
PyObject *bimod, *sysmod;
154+
PyObject *bimod, *sysmod, *pstderr;
155155
char *p;
156156
#if defined(HAVE_LANGINFO_H) && defined(CODESET)
157157
char *codeset;
@@ -228,6 +228,13 @@ Py_InitializeEx(int install_sigs)
228228
PyDict_SetItemString(interp->sysdict, "modules",
229229
interp->modules);
230230

231+
/* Set up a preliminary stderr printer until we have enough
232+
infrastructure for the io module in place. */
233+
pstderr = PyFile_NewStdPrinter(fileno(stderr));
234+
if (pstderr == NULL)
235+
Py_FatalError("Py_Initialize: can't set preliminary stderr");
236+
PySys_SetObject("stderr", pstderr);
237+
231238
_PyImport_Init();
232239

233240
/* initialize builtin exceptions */

0 commit comments

Comments
 (0)