Tom Lane escribió: > "Marko Kreen" <[EMAIL PROTECTED]> writes: > > Following function crashes plpython on x86-64 / gcc 4.1.2 / debian 4.0: > > CREATE FUNCTION crashme(str_len integer) > > RETURNS text AS $$ > > raise Exception("X" * str_len) > > $$ LANGUAGE plpythonu; > > > SELECT crashme(1000); > > > Problem turns out to be va_list handling in PLy_vprintf() which > > uses same va_list repeatedly. Fix is to va_copy to temp variable. > > This patch isn't acceptable because va_copy() isn't portable. > > I'm kinda wondering why PLy_printf and the functions after it even > exist. They look like rather poorly done reimplementations of > functionality that exists elsewhere in the backend (eg, stringinfo.c). > In particular, why malloc and not palloc?
See attached patch. I didn't bother to change the PLy_malloc and friends because I think that would be too much change for 8.3. PLy_realloc is gone though because there are no callers left after this patch. -- Alvaro Herrera http://www.flickr.com/photos/alvherre/ "Ninguna manada de bestias tiene una voz tan horrible como la humana" (Orual)
Index: src/pl/plpython/plpython.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/pl/plpython/plpython.c,v retrieving revision 1.104 diff -c -p -r1.104 plpython.c *** src/pl/plpython/plpython.c 15 Nov 2007 21:14:46 -0000 1.104 --- src/pl/plpython/plpython.c 22 Nov 2007 18:11:02 -0000 *************** static char *PLy_procedure_name(PLyProce *** 210,220 **** /* some utility functions */ static void PLy_elog(int, const char *,...); static char *PLy_traceback(int *); - static char *PLy_vprintf(const char *fmt, va_list ap); - static char *PLy_printf(const char *fmt,...); static void *PLy_malloc(size_t); - static void *PLy_realloc(void *, size_t); static char *PLy_strdup(const char *); static void PLy_free(void *); --- 210,217 ---- *************** PLy_exception_set(PyObject * exc, const *** 2900,2934 **** static void PLy_elog(int elevel, const char *fmt,...) { ! va_list ap; ! char *xmsg, ! *emsg; int xlevel; xmsg = PLy_traceback(&xlevel); ! va_start(ap, fmt); ! emsg = PLy_vprintf(fmt, ap); ! va_end(ap); PG_TRY(); { ereport(elevel, ! (errmsg("plpython: %s", emsg), (xmsg) ? errdetail("%s", xmsg) : 0)); } PG_CATCH(); { ! PLy_free(emsg); if (xmsg) ! PLy_free(xmsg); PG_RE_THROW(); } PG_END_TRY(); ! PLy_free(emsg); if (xmsg) ! PLy_free(xmsg); } static char * --- 2897,2940 ---- static void PLy_elog(int elevel, const char *fmt,...) { ! char *xmsg; int xlevel; + StringInfoData emsg; xmsg = PLy_traceback(&xlevel); ! initStringInfo(&emsg); ! for (;;) ! { ! va_list ap; ! bool success; ! ! va_start(ap, fmt); ! success = appendStringInfoVA(&emsg, fmt, ap); ! va_end(ap); ! if (success) ! break; ! enlargeStringInfo(&emsg, emsg.maxlen); ! } PG_TRY(); { ereport(elevel, ! (errmsg("plpython: %s", emsg.data), (xmsg) ? errdetail("%s", xmsg) : 0)); } PG_CATCH(); { ! pfree(emsg.data); if (xmsg) ! pfree(xmsg); PG_RE_THROW(); } PG_END_TRY(); ! pfree(emsg.data); if (xmsg) ! pfree(xmsg); } static char * *************** PLy_traceback(int *xlevel) *** 2940,2947 **** PyObject *eob, *vob = NULL; char *vstr, ! *estr, ! *xstr = NULL; /* * get the current exception --- 2946,2953 ---- PyObject *eob, *vob = NULL; char *vstr, ! *estr; ! StringInfoData xstr; /* * get the current exception *************** PLy_traceback(int *xlevel) *** 2973,2979 **** * Assert() be more appropriate? */ estr = eob ? PyString_AsString(eob) : "Unknown Exception"; ! xstr = PLy_printf("%s: %s", estr, vstr); Py_DECREF(eob); Py_XDECREF(vob); --- 2979,2986 ---- * Assert() be more appropriate? */ estr = eob ? PyString_AsString(eob) : "Unknown Exception"; ! initStringInfo(&xstr); ! appendStringInfo(&xstr, "%s: %s", estr, vstr); Py_DECREF(eob); Py_XDECREF(vob); *************** PLy_traceback(int *xlevel) *** 2990,3038 **** *xlevel = ERROR; Py_DECREF(e); ! return xstr; ! } ! ! static char * ! PLy_printf(const char *fmt,...) ! { ! va_list ap; ! char *emsg; ! ! va_start(ap, fmt); ! emsg = PLy_vprintf(fmt, ap); ! va_end(ap); ! return emsg; ! } ! ! static char * ! PLy_vprintf(const char *fmt, va_list ap) ! { ! size_t blen; ! int bchar, ! tries = 2; ! char *buf; ! ! blen = strlen(fmt) * 2; ! if (blen < 256) ! blen = 256; ! buf = PLy_malloc(blen * sizeof(char)); ! ! while (1) ! { ! bchar = vsnprintf(buf, blen, fmt, ap); ! if (bchar > 0 && bchar < blen) ! return buf; ! if (tries-- <= 0) ! break; ! if (blen > 0) ! blen = bchar + 1; ! else ! blen *= 2; ! buf = PLy_realloc(buf, blen); ! } ! PLy_free(buf); ! return NULL; } /* python module code */ --- 2997,3003 ---- *xlevel = ERROR; Py_DECREF(e); ! return xstr.data; } /* python module code */ *************** PLy_malloc(size_t bytes) *** 3050,3067 **** return ptr; } - static void * - PLy_realloc(void *optr, size_t bytes) - { - void *nptr = realloc(optr, bytes); - - if (nptr == NULL) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return nptr; - } - static char * PLy_strdup(const char *str) { --- 3015,3020 ----
---------------------------(end of broadcast)--------------------------- TIP 2: Don't 'kill -9' the postmaster