diff --git a/src/pl/plpython/plpy_elog.c b/src/pl/plpython/plpy_elog.c new file mode 100644 index c375ac0..c2b3cb8 *** 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 *************** PLy_traceback(char **xmsg, char **tbmsg, *** 147,166 **** StringInfoData xstr; StringInfoData tbstr; /* * get the current exception */ PyErr_Fetch(&e, &v, &tb); /* ! * oops, no exception, return */ ! if (e == NULL) { *xmsg = NULL; *tbmsg = NULL; *tb_depth = 0; return; } --- 155,177 ---- StringInfoData xstr; StringInfoData tbstr; + recursion_depth++; + /* * get the current exception */ PyErr_Fetch(&e, &v, &tb); /* ! * oops, no exception or recursion depth exceeded, return */ ! if (e == NULL || recursion_depth > TRACEBACK_RECURSION_LIMIT) { *xmsg = NULL; *tbmsg = NULL; *tb_depth = 0; + recursion_depth--; return; } *************** PLy_traceback(char **xmsg, char **tbmsg, *** 326,331 **** --- 337,344 ---- (*tb_depth)++; } + recursion_depth--; + /* Return the traceback. */ *tbmsg = tbstr.data; diff --git a/src/pl/plpython/plpy_util.c b/src/pl/plpython/plpy_util.c new file mode 100644 index bf29532..ea4ecdf *** a/src/pl/plpython/plpy_util.c --- b/src/pl/plpython/plpy_util.c *************** PLyUnicode_Bytes(PyObject *unicode) *** 112,117 **** --- 112,123 ---- case PG_WIN874: serverenc = "cp874"; break; + case PG_KOI8R: + serverenc = "koi8-r"; + break; + case PG_KOI8U: + serverenc = "koi8-u"; + break; default: /* Other encodings have the same name in Python. */ serverenc = GetDatabaseEncodingName(); *************** PLyUnicode_Bytes(PyObject *unicode) *** 120,135 **** rv = PyUnicode_AsEncodedString(unicode, serverenc, "strict"); if (rv == NULL) ! { ! /* ! * Use a plain ereport instead of PLy_elog to avoid recursion, if ! * the traceback formatting functions try to do unicode to bytes ! * conversion again. ! */ ! ereport(ERROR, ! (errcode(ERRCODE_INTERNAL_ERROR), ! errmsg("could not convert Python Unicode object to PostgreSQL server encoding"))); ! } return rv; } --- 126,132 ---- rv = PyUnicode_AsEncodedString(unicode, serverenc, "strict"); if (rv == NULL) ! PLy_elog(ERROR, "could not convert Python Unicode object to PostgreSQL server encoding"); return rv; }