Thread: Re: Problem with dblink

Re: Problem with dblink

From
Joe Conway
Date:
Andrea Grassi wrote:

[...using dblink_build_sql_insert() inside a PL/pgSQL function...]

> ERROR:  improper call to spi_printtup
> CONTEXT:  PL/pgSQL function "f_sync_trigger_a_clifor" line 6 at select into
> variables

Attached fixes a recently reported bug in dblink. If there are no
objections, I'll make this my first commit :-)

I intend to apply it to HEAD and REL7_4_STABLE, but it could also be
applied to REL7_3_STABLE -- any opinions on that? Are we still
considering a 7.3.5 release?

Thanks,

Joe
Index: dblink.c
===================================================================
RCS file: /opt/src/cvs/pgsql-server/contrib/dblink/dblink.c,v
retrieving revision 1.27
diff -c -r1.27 dblink.c
*** dblink.c    12 Nov 2003 21:15:42 -0000    1.27
--- dblink.c    21 Nov 2003 18:26:17 -0000
***************
*** 1766,1771 ****
--- 1766,1772 ----
          SPITupleTable *tuptable = SPI_tuptable;

          tuple = SPI_copytuple(tuptable->vals[0]);
+         SPI_finish();

          return tuple;
      }
***************
*** 1774,1779 ****
--- 1775,1782 ----
          /*
           * no qualifying tuples
           */
+         SPI_finish();
+
          return NULL;
      }


Re: Problem with dblink

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Attached fixes a recently reported bug in dblink. If there are no
> objections, I'll make this my first commit :-)

Looks right to me; but as a general tip, if you've made mistake X in
place A, you might have made it in place B too.  Have you checked the
rest of dblink for forgotten SPI_finish calls?

(More generally, I wonder if AtEOXact_SPI oughtn't be fixed to emit
a WARNING if the SPI stack isn't empty, except in the error case.
Neglecting SPI_finish is analogous to a resource leak, and we have
code in place to warn about other sorts of leaks.)

> I intend to apply it to HEAD and REL7_4_STABLE, but it could also be
> applied to REL7_3_STABLE -- any opinions on that? Are we still
> considering a 7.3.5 release?

Sure.  I believe we still intend a 7.3.5 shortly (maybe early December,
since Thanksgiving week is a bad time to expect anything to happen).

            regards, tom lane

Re: Problem with dblink

From
Joe Conway
Date:
Tom Lane wrote:
> Looks right to me; but as a general tip, if you've made mistake X in
> place A, you might have made it in place B too.  Have you checked the
> rest of dblink for forgotten SPI_finish calls?

Good tip -- will do. Though, I suspect the dblink_build_sql_* functions
have been much more lightly used than the rest of dblink, and that's the
only reason this bug has lurked for so long.

> (More generally, I wonder if AtEOXact_SPI oughtn't be fixed to emit
> a WARNING if the SPI stack isn't empty, except in the error case.
> Neglecting SPI_finish is analogous to a resource leak, and we have
> code in place to warn about other sorts of leaks.)

I'll take a look at this too.

> Sure.  I believe we still intend a 7.3.5 shortly (maybe early December,
> since Thanksgiving week is a bad time to expect anything to happen).
>

OK -- then I'll plan to apply the final fix to REL7_3_STABLE as well.

Thanks,

Joe




Re: Problem with dblink

From
Joe Conway
Date:
Tom Lane wrote:
> Looks right to me; but as a general tip, if you've made mistake X in
> place A, you might have made it in place B too.  Have you checked the
> rest of dblink for forgotten SPI_finish calls?

That function was the only one using SPI calls in dblink, so there were
no others. Fix applied to head, 7.3 stable, and 7.4 stable.

> (More generally, I wonder if AtEOXact_SPI oughtn't be fixed to emit
> a WARNING if the SPI stack isn't empty, except in the error case.
> Neglecting SPI_finish is analogous to a resource leak, and we have
> code in place to warn about other sorts of leaks.)

I'll look at this separately. Changes in this regard only belong applied
to cvs head I assume.

Joe


Re: Problem with dblink

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Tom Lane wrote:
>> (More generally, I wonder if AtEOXact_SPI oughtn't be fixed to emit
>> a WARNING if the SPI stack isn't empty, except in the error case.
>> Neglecting SPI_finish is analogous to a resource leak, and we have
>> code in place to warn about other sorts of leaks.)

> I'll look at this separately. Changes in this regard only belong applied
> to cvs head I assume.

Yeah, I think to apply it to a stable branch you'd want some indication
that there are more live bugs out there that it's needed to catch.  At
the moment it only seems called for as an aid to future development, and
so HEAD seems sufficient.

            regards, tom lane

Re: Problem with dblink

From
Joe Conway
Date:
Tom Lane wrote:
> Yeah, I think to apply it to a stable branch you'd want some indication
> that there are more live bugs out there that it's needed to catch.  At
> the moment it only seems called for as an aid to future development, and
> so HEAD seems sufficient.
>

Thanks, that's what i thought.

On a loosely related question, I didn't see commit messages for my
commits. Am I supposed to do something specific to cause them to be emitted?

Joe



Re: Problem with dblink

From
Christopher Kings-Lynne
Date:
> Thanks, that's what i thought.
>
> On a loosely related question, I didn't see commit messages for my
> commits. Am I supposed to do something specific to cause them to be
> emitted?

I saw them, "User Joe" :)

CVSROOT:    /cvsroot
Module name:    pgsql-server
Changes by:    joe@svr1.postgresql.org    03/11/26 16:43:25

Modified files:
    contrib/dblink : dblink.c

Log message:
    Added missing SPI_finish() calls to get_tuple_of_interest(). Fixes bug
    reported by Andrea Grassi.

...and the rest...

Chris



Re: Problem with dblink

From
Joe Conway
Date:
Christopher Kings-Lynne wrote:
> I saw them, "User Joe" :)
>

Yeah, they just showed up for me too. I'll have to figure out how to
change that from "User Joe" to something else -- sounds kind of strange ;-)

Joe


Re: Problem with dblink

From
Bruce Momjian
Date:
Joe Conway wrote:
> Christopher Kings-Lynne wrote:
> > I saw them, "User Joe" :)
> >
>
> Yeah, they just showed up for me too. I'll have to figure out how to
> change that from "User Joe" to something else -- sounds kind of strange ;-)

Marc just fixed it.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: Problem with dblink

From
Larry Rosenman
Date:
On Wed, 26 Nov 2003, Joe Conway wrote:

> Tom Lane wrote:
> > Yeah, I think to apply it to a stable branch you'd want some indication
> > that there are more live bugs out there that it's needed to catch.  At
> > the moment it only seems called for as an aid to future development, and
> > so HEAD seems sufficient.
> >
>
> Thanks, that's what i thought.
>
> On a loosely related question, I didn't see commit messages for my
> commits. Am I supposed to do something specific to cause them to be emitted?
I did see them (although you ought to get Marc to change the Real Name
field to show Joe Conway instead of User joe).

LER

>
> Joe
>
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
>
>

--
Larry Rosenman                     http://www.lerctr.org/~ler
Phone: +1 972-414-9812                 E-Mail: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Problem with dblink

From
Larry Rosenman
Date:
On Wed, 26 Nov 2003, Joe Conway wrote:

> Christopher Kings-Lynne wrote:
> > I saw them, "User Joe" :)
> >
>
> Yeah, they just showed up for me too. I'll have to figure out how to
> change that from "User Joe" to something else -- sounds kind of strange
;-)
Does Marc allow chfn to run on those boxes?

If so, run it. :-)

LER

>
> Joe
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 8: explain analyze is your friend
>
>

--
Larry Rosenman                     http://www.lerctr.org/~ler
Phone: +1 972-414-9812                 E-Mail: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749


Re: Problem with dblink

From
Joe Conway
Date:
Bruce Momjian wrote:
> Joe Conway wrote:
>>Yeah, they just showed up for me too. I'll have to figure out how to
>>change that from "User Joe" to something else -- sounds kind of strange ;-)
>
> Marc just fixed it.
>

Ah, great! Thanks Marc :-)

Joe


Re: Problem with dblink

From
Joe Conway
Date:
>>Tom Lane wrote:
>>>(More generally, I wonder if AtEOXact_SPI oughtn't be fixed to emit
>>>a WARNING if the SPI stack isn't empty, except in the error case.
>>>Neglecting SPI_finish is analogous to a resource leak, and we have
>>>code in place to warn about other sorts of leaks.)

Is the attached what you had in mind? The original problem function
would now look like:

SELECT dblink_build_sql_insert('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
WARNING:  freeing non-empty SPI stack
HINT:  Check for missing "SPI_finish" calls
                   dblink_build_sql_insert
-----------------------------------------------------------
  INSERT INTO foo(f1,f2,f3) VALUES('99','xyz','{a0,b0,c0}')
(1 row)

Joe

Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/access/transam/xact.c,v
retrieving revision 1.157
diff -c -r1.157 xact.c
*** src/backend/access/transam/xact.c    29 Nov 2003 19:51:40 -0000    1.157
--- src/backend/access/transam/xact.c    29 Nov 2003 23:57:09 -0000
***************
*** 977,983 ****

      CallEOXactCallbacks(true);
      AtEOXact_GUC(true);
!     AtEOXact_SPI();
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
--- 977,983 ----

      CallEOXactCallbacks(true);
      AtEOXact_GUC(true);
!     AtEOXact_SPI(false);
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
***************
*** 1087,1093 ****

      CallEOXactCallbacks(false);
      AtEOXact_GUC(false);
!     AtEOXact_SPI();
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
--- 1087,1093 ----

      CallEOXactCallbacks(false);
      AtEOXact_GUC(false);
!     AtEOXact_SPI(true);
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
Index: src/backend/executor/spi.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/executor/spi.c,v
retrieving revision 1.108
diff -c -r1.108 spi.c
*** src/backend/executor/spi.c    29 Nov 2003 19:51:48 -0000    1.108
--- src/backend/executor/spi.c    29 Nov 2003 23:57:09 -0000
***************
*** 177,191 ****
   * Clean up SPI state at transaction commit or abort (we don't care which).
   */
  void
! AtEOXact_SPI(void)
  {
      /*
       * Note that memory contexts belonging to SPI stack entries will be
       * freed automatically, so we can ignore them here.  We just need to
       * restore our static variables to initial state.
       */
!     if (_SPI_stack != NULL)        /* there was abort */
          free(_SPI_stack);
      _SPI_current = _SPI_stack = NULL;
      _SPI_connected = _SPI_curid = -1;
      SPI_processed = 0;
--- 177,199 ----
   * Clean up SPI state at transaction commit or abort (we don't care which).
   */
  void
! AtEOXact_SPI(bool isAbort)
  {
      /*
       * Note that memory contexts belonging to SPI stack entries will be
       * freed automatically, so we can ignore them here.  We just need to
       * restore our static variables to initial state.
       */
!     if (_SPI_stack != NULL)
!     {
          free(_SPI_stack);
+         if (!isAbort)
+             ereport(WARNING,
+                     (errcode(ERRCODE_WARNING),
+                      errmsg("freeing non-empty SPI stack"),
+                      errhint("Check for missing \"SPI_finish\" calls")));
+     }
+
      _SPI_current = _SPI_stack = NULL;
      _SPI_connected = _SPI_curid = -1;
      SPI_processed = 0;
Index: src/include/executor/spi.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/executor/spi.h,v
retrieving revision 1.40
diff -c -r1.40 spi.h
*** src/include/executor/spi.h    29 Nov 2003 22:41:01 -0000    1.40
--- src/include/executor/spi.h    29 Nov 2003 23:57:09 -0000
***************
*** 116,121 ****
  extern void SPI_cursor_move(Portal portal, bool forward, int count);
  extern void SPI_cursor_close(Portal portal);

! extern void AtEOXact_SPI(void);

  #endif   /* SPI_H */
--- 116,121 ----
  extern void SPI_cursor_move(Portal portal, bool forward, int count);
  extern void SPI_cursor_close(Portal portal);

! extern void AtEOXact_SPI(bool isAbort);

  #endif   /* SPI_H */

Re: Problem with dblink

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Tom Lane wrote:
> (More generally, I wonder if AtEOXact_SPI oughtn't be fixed to emit
> a WARNING if the SPI stack isn't empty, except in the error case.
> Neglecting SPI_finish is analogous to a resource leak, and we have
> code in place to warn about other sorts of leaks.)

> Is the attached what you had in mind?

Approximately.  A couple minor stylistic gripes:

1. AFAIR, all the other at-end-of-xact routines that take a flag telling
them if it's commit or abort define the flag as isCommit.  Having the
reverse convention for this one routine is confusing and a recipe for
errors, so please make it be isCommit too.

2. The initial comment for AtEOXact_SPI:

>    * Clean up SPI state at transaction commit or abort (we don't care which).

is now incorrect and needs to be updated (at least get rid of the
parenthetical note).

> !     if (_SPI_stack != NULL)
> !     {
>           free(_SPI_stack);
> +         if (!isAbort)
> +             ereport(WARNING,
> +                     (errcode(ERRCODE_WARNING),
> +                      errmsg("freeing non-empty SPI stack"),
> +                      errhint("Check for missing \"SPI_finish\" calls")));
> +     }
> +

While this isn't necessarily wrong, what would probably be a stronger
test is to complain if either _SPI_connected or _SPI_curid is not -1.
For one thing that would catch missing SPI_pop().  (Jan, any comment
about that?)

            regards, tom lane

Re: Problem with dblink

From
Joe Conway
Date:
Tom Lane wrote:
> 1. AFAIR, all the other at-end-of-xact routines that take a flag telling
> them if it's commit or abort define the flag as isCommit.  Having the
> reverse convention for this one routine is confusing and a recipe for
> errors, so please make it be isCommit too.

Done.

> 2. The initial comment for AtEOXact_SPI:
>
>>   * Clean up SPI state at transaction commit or abort (we don't care which).
>
> is now incorrect and needs to be updated (at least get rid of the
> parenthetical note).

Done.

>>!     if (_SPI_stack != NULL)
>>!     {
>>          free(_SPI_stack);
>>+         if (!isAbort)
>>+             ereport(WARNING,
>>+                     (errcode(ERRCODE_WARNING),
>>+                      errmsg("freeing non-empty SPI stack"),
>>+                      errhint("Check for missing \"SPI_finish\" calls")));
>>+     }
>>+
>
> While this isn't necessarily wrong, what would probably be a stronger
> test is to complain if either _SPI_connected or _SPI_curid is not -1.
> For one thing that would catch missing SPI_pop().  (Jan, any comment
> about that?)
>

Based on some simple testing, a warning for (_SPI_connected != -1) seems
redundant with (_SPI_stack != NULL) -- i.e. I just get both warnings
when SPI_finish() isn't called. And commenting out SPI_pop() causes a
"SPI_finish failed" error, at least in the one place it's used
(pl_exec.c), so we never get to AtEOXact_SPI(). So for the moment at
least I left that last section the same.

OK to commit?

Joe

Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/access/transam/xact.c,v
retrieving revision 1.157
diff -c -r1.157 xact.c
*** src/backend/access/transam/xact.c    29 Nov 2003 19:51:40 -0000    1.157
--- src/backend/access/transam/xact.c    1 Dec 2003 03:50:40 -0000
***************
*** 977,983 ****

      CallEOXactCallbacks(true);
      AtEOXact_GUC(true);
!     AtEOXact_SPI();
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
--- 977,983 ----

      CallEOXactCallbacks(true);
      AtEOXact_GUC(true);
!     AtEOXact_SPI(true);
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
***************
*** 1087,1093 ****

      CallEOXactCallbacks(false);
      AtEOXact_GUC(false);
!     AtEOXact_SPI();
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
--- 1087,1093 ----

      CallEOXactCallbacks(false);
      AtEOXact_GUC(false);
!     AtEOXact_SPI(false);
      AtEOXact_gist();
      AtEOXact_hash();
      AtEOXact_nbtree();
Index: src/backend/executor/spi.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/executor/spi.c,v
retrieving revision 1.108
diff -c -r1.108 spi.c
*** src/backend/executor/spi.c    29 Nov 2003 19:51:48 -0000    1.108
--- src/backend/executor/spi.c    1 Dec 2003 03:50:40 -0000
***************
*** 174,191 ****
  }

  /*
!  * Clean up SPI state at transaction commit or abort (we don't care which).
   */
  void
! AtEOXact_SPI(void)
  {
      /*
       * Note that memory contexts belonging to SPI stack entries will be
       * freed automatically, so we can ignore them here.  We just need to
       * restore our static variables to initial state.
       */
!     if (_SPI_stack != NULL)        /* there was abort */
          free(_SPI_stack);
      _SPI_current = _SPI_stack = NULL;
      _SPI_connected = _SPI_curid = -1;
      SPI_processed = 0;
--- 174,199 ----
  }

  /*
!  * Clean up SPI state at transaction commit or abort.
   */
  void
! AtEOXact_SPI(bool isCommit)
  {
      /*
       * Note that memory contexts belonging to SPI stack entries will be
       * freed automatically, so we can ignore them here.  We just need to
       * restore our static variables to initial state.
       */
!     if (_SPI_stack != NULL)
!     {
          free(_SPI_stack);
+         if (isCommit)
+             ereport(WARNING,
+                     (errcode(ERRCODE_WARNING),
+                      errmsg("freeing non-empty SPI stack"),
+                      errhint("Check for missing \"SPI_finish\" calls")));
+     }
+
      _SPI_current = _SPI_stack = NULL;
      _SPI_connected = _SPI_curid = -1;
      SPI_processed = 0;
Index: src/include/executor/spi.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/executor/spi.h,v
retrieving revision 1.40
diff -c -r1.40 spi.h
*** src/include/executor/spi.h    29 Nov 2003 22:41:01 -0000    1.40
--- src/include/executor/spi.h    1 Dec 2003 03:50:43 -0000
***************
*** 116,121 ****
  extern void SPI_cursor_move(Portal portal, bool forward, int count);
  extern void SPI_cursor_close(Portal portal);

! extern void AtEOXact_SPI(void);

  #endif   /* SPI_H */
--- 116,121 ----
  extern void SPI_cursor_move(Portal portal, bool forward, int count);
  extern void SPI_cursor_close(Portal portal);

! extern void AtEOXact_SPI(bool isCommit);

  #endif   /* SPI_H */