diff --git a/Cython/Utility/Printing.c b/Cython/Utility/Printing.c index 887bc313689777fbd42f904d9364a1766ae89768..4dddfd1f2f86e88532bb5b363efb17e421bec92a 100644 --- a/Cython/Utility/Printing.c +++ b/Cython/Utility/Printing.c @@ -30,14 +30,15 @@ static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) { if (!(f = __Pyx_GetStdout())) return -1; } + Py_INCREF(f); for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) { if (PyFile_SoftSpace(f, 1)) { if (PyFile_WriteString(" ", f) < 0) - return -1; + goto error; } v = PyTuple_GET_ITEM(arg_tuple, i); if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) - return -1; + goto error; if (PyString_Check(v)) { char *s = PyString_AsString(v); Py_ssize_t len = PyString_Size(v); @@ -49,10 +50,14 @@ static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) { } if (newline) { if (PyFile_WriteString("\n", f) < 0) - return -1; + goto error; PyFile_SoftSpace(f, 0); } + Py_DECREF(f); return 0; +error: + Py_DECREF(f); + return -1; } #else /* Python 3 has a print function */ @@ -125,15 +130,20 @@ static int __Pyx_PrintOne(PyObject* f, PyObject *o) { if (!(f = __Pyx_GetStdout())) return -1; } + Py_INCREF(f); if (PyFile_SoftSpace(f, 0)) { if (PyFile_WriteString(" ", f) < 0) - return -1; + goto error; } if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0) - return -1; + goto error; if (PyFile_WriteString("\n", f) < 0) - return -1; + goto error; + Py_DECREF(f); return 0; +error: + Py_DECREF(f); + return -1; /* the line below is just to avoid compiler * compiler warnings about unused functions */ return __Pyx_Print(f, NULL, 0); diff --git a/tests/run/print_refcount.pyx b/tests/run/print_refcount.pyx new file mode 100644 index 0000000000000000000000000000000000000000..e2d4e5a7220d492157a660ba2f7350c5e6931266 --- /dev/null +++ b/tests/run/print_refcount.pyx @@ -0,0 +1,40 @@ +# mode: run +import sys + +def test_print_refcount(): + """ + >>> test_print_refcount() + """ + old_stdout = sys.stdout + class StdoutGuard: + def __getattr__(self, attr): + sys.stdout = old_stdout + raise RuntimeError + sys.stdout = StdoutGuard() + try: + print "Hello", "world!" + except RuntimeError: + pass + finally: + sys.stdout = old_stdout + class TriggerSIGSEGV(object): + pass + +def test_printone_refcount(): + """ + >>> test_printone_refcount() + """ + old_stdout = sys.stdout + class StdoutGuard: + def __getattr__(self, attr): + sys.stdout = old_stdout + raise RuntimeError + sys.stdout = StdoutGuard() + try: + print "Oops!" + except RuntimeError: + pass + finally: + sys.stdout = old_stdout + class TriggerSIGSEGV(object): + pass