diff --git a/src/pl/plpython/plpy_elog.c b/src/pl/plpython/plpy_elog.c new file mode 100644 index c375ac0..9944f72 *** a/src/pl/plpython/plpy_elog.c --- b/src/pl/plpython/plpy_elog.c *************** static char *get_source_line(const char *** 28,33 **** --- 28,41 ---- /* + * Guard agains re-entrant calls to PLy_traceback, which can happen if + * traceback formatting functions raise Python errors. + */ + #define TRACEBACK_RECURSION_LIMIT 2 + static int recursion_depth = 0; + + + /* * Emit a PG error or notice, together with any available info about * the current Python error, previously set by PLy_exception_set(). * This should be used to propagate Python errors into PG. If fmt is *************** static char *get_source_line(const char *** 38,46 **** void PLy_elog(int elevel, const char *fmt,...) { ! char *xmsg; ! char *tbmsg; ! int tb_depth; StringInfoData emsg; PyObject *exc, *val, --- 46,54 ---- void PLy_elog(int elevel, const char *fmt,...) { ! char *xmsg = NULL; ! char *tbmsg = NULL; ! int tb_depth = 0; StringInfoData emsg; PyObject *exc, *val, *************** PLy_elog(int elevel, const char *fmt,... *** 62,68 **** } PyErr_Restore(exc, val, tb); ! PLy_traceback(&xmsg, &tbmsg, &tb_depth); if (fmt) { --- 70,90 ---- } PyErr_Restore(exc, val, tb); ! if (recursion_depth++ <= TRACEBACK_RECURSION_LIMIT) ! { ! PG_TRY(); ! { ! PLy_traceback(&xmsg, &tbmsg, &tb_depth); ! } ! PG_CATCH(); ! { ! recursion_depth--; ! PG_RE_THROW(); ! } ! PG_END_TRY(); ! } ! ! recursion_depth--; if (fmt) { diff --git a/src/pl/plpython/plpy_util.c b/src/pl/plpython/plpy_util.c new file mode 100644 index 4aabafc..94c035e *** a/src/pl/plpython/plpy_util.c --- b/src/pl/plpython/plpy_util.c *************** PLy_free(void *ptr) *** 61,126 **** PyObject * PLyUnicode_Bytes(PyObject *unicode) { ! PyObject *rv; ! const char *serverenc; ! /* ! * Map PostgreSQL encoding to a Python encoding name. ! */ ! switch (GetDatabaseEncoding()) { ! case PG_SQL_ASCII: ! /* ! * Mapping SQL_ASCII to Python's 'ascii' is a bit bogus. Python's ! * 'ascii' means true 7-bit only ASCII, while PostgreSQL's ! * SQL_ASCII means that anything is allowed, and the system doesn't ! * try to interpret the bytes in any way. But not sure what else ! * to do, and we haven't heard any complaints... ! */ ! serverenc = "ascii"; ! break; ! case PG_WIN1250: ! serverenc = "cp1250"; ! break; ! case PG_WIN1251: ! serverenc = "cp1251"; ! break; ! case PG_WIN1252: ! serverenc = "cp1252"; ! break; ! case PG_WIN1253: ! serverenc = "cp1253"; ! break; ! case PG_WIN1254: ! serverenc = "cp1254"; ! break; ! case PG_WIN1255: ! serverenc = "cp1255"; ! break; ! case PG_WIN1256: ! serverenc = "cp1256"; ! break; ! case PG_WIN1257: ! serverenc = "cp1257"; ! break; ! case PG_WIN1258: ! serverenc = "cp1258"; ! break; ! case PG_WIN866: ! serverenc = "cp866"; ! break; ! case PG_WIN874: ! serverenc = "cp874"; ! break; ! default: ! /* Other encodings have the same name in Python. */ ! serverenc = GetDatabaseEncodingName(); ! break; } ! rv = PyUnicode_AsEncodedString(unicode, serverenc, "strict"); ! if (rv == NULL) ! PLy_elog(ERROR, "could not convert Python Unicode object to PostgreSQL server encoding"); return rv; } --- 61,106 ---- PyObject * PLyUnicode_Bytes(PyObject *unicode) { ! PyObject *bytes, *rv; ! char *utf8string, *encoded; ! /* first encode the Python unicode object with UTF-8 */ ! bytes = PyUnicode_AsUTF8String(unicode); ! if (bytes == NULL) ! PLy_elog(ERROR, "could not convert Python Unicode object to bytes"); ! ! utf8string = PyBytes_AsString(bytes); ! if (utf8string == NULL) { ! Py_DECREF(bytes); ! PLy_elog(ERROR, "could not extract bytes from encoded string"); ! } ! ! /* then convert to server encoding */ ! PG_TRY(); { ! encoded = (char *) pg_do_encoding_conversion( ! (unsigned char *) utf8string, ! strlen(utf8string), ! PG_UTF8, ! GetDatabaseEncoding()); ! } ! PG_CATCH(); ! { ! Py_DECREF(bytes); ! PG_RE_THROW(); } + PG_END_TRY(); ! /* finally, build a bytes object in the server encoding */ ! rv = PyBytes_FromStringAndSize(encoded, strlen(encoded)); ! ! /* if pg_do_encoding_conversion allocated memory, free it now */ ! if (utf8string != encoded) ! { ! pfree(encoded); ! } ! ! Py_DECREF(bytes); return rv; }