@@ -4510,6 +4510,14 @@ get_source_line(const char *src, int lineno)
4510
4510
if (next == NULL )
4511
4511
return pstrdup (s );
4512
4512
4513
+ /*
4514
+ * Sanity check, next < s if the line was all-whitespace, which should
4515
+ * never happen if Python reported a frame created on that line, but
4516
+ * check anyway.
4517
+ */
4518
+ if (next < s )
4519
+ return NULL ;
4520
+
4513
4521
return pnstrdup (s , next - s );
4514
4522
}
4515
4523
@@ -4606,6 +4614,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
4606
4614
PyObject * volatile code = NULL ;
4607
4615
PyObject * volatile name = NULL ;
4608
4616
PyObject * volatile lineno = NULL ;
4617
+ PyObject * volatile filename = NULL ;
4609
4618
4610
4619
PG_TRY ();
4611
4620
{
@@ -4624,13 +4633,18 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
4624
4633
name = PyObject_GetAttrString (code , "co_name" );
4625
4634
if (name == NULL )
4626
4635
elog (ERROR , "could not get function name from Python code object" );
4636
+
4637
+ filename = PyObject_GetAttrString (code , "co_filename" );
4638
+ if (filename == NULL )
4639
+ elog (ERROR , "could not get file name from Python code object" );
4627
4640
}
4628
4641
PG_CATCH ();
4629
4642
{
4630
4643
Py_XDECREF (frame );
4631
4644
Py_XDECREF (code );
4632
4645
Py_XDECREF (name );
4633
4646
Py_XDECREF (lineno );
4647
+ Py_XDECREF (filename );
4634
4648
PG_RE_THROW ();
4635
4649
}
4636
4650
PG_END_TRY ();
@@ -4641,6 +4655,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
4641
4655
char * proname ;
4642
4656
char * fname ;
4643
4657
char * line ;
4658
+ char * plain_filename ;
4644
4659
long plain_lineno ;
4645
4660
4646
4661
/*
@@ -4653,6 +4668,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
4653
4668
fname = PyString_AsString (name );
4654
4669
4655
4670
proname = PLy_procedure_name (PLy_curr_procedure );
4671
+ plain_filename = PyString_AsString (filename );
4656
4672
plain_lineno = PyInt_AsLong (lineno );
4657
4673
4658
4674
if (proname == NULL )
@@ -4664,15 +4680,18 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
4664
4680
& tbstr , "\n PL/Python function \"%s\", line %ld, in %s" ,
4665
4681
proname , plain_lineno - 1 , fname );
4666
4682
4667
- if (PLy_curr_procedure )
4683
+ /* function code object was compiled with "<string>" as the filename */
4684
+ if (PLy_curr_procedure && plain_filename != NULL &&
4685
+ strcmp (plain_filename , "<string>" ) == 0 )
4668
4686
{
4669
4687
/*
4670
4688
* If we know the current procedure, append the exact line
4671
4689
* from the source, again mimicking Python's traceback.py
4672
4690
* module behavior. We could store the already line-split
4673
4691
* source to avoid splitting it every time, but producing a
4674
4692
* traceback is not the most important scenario to optimize
4675
- * for.
4693
+ * for. But we do not go as far as traceback.py in reading
4694
+ * the source of imported modules.
4676
4695
*/
4677
4696
line = get_source_line (PLy_curr_procedure -> src , plain_lineno );
4678
4697
if (line )
@@ -4687,6 +4706,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
4687
4706
Py_DECREF (code );
4688
4707
Py_DECREF (name );
4689
4708
Py_DECREF (lineno );
4709
+ Py_DECREF (filename );
4690
4710
4691
4711
/* Release the current frame and go to the next one. */
4692
4712
tb_prev = tb ;
0 commit comments