2013-01-02 16:27 keltezéssel, Marko Kreen írta:
On Wed, Jan 2, 2013 at 5:11 PM, Boszormenyi Zoltan <z...@cybertec.at> wrote:
2012-12-11 16:09 keltezéssel, Simon Riggs írta:

On 11 December 2012 12:18, Boszormenyi Zoltan <z...@cybertec.at> wrote:

Such mechanism already exist - you just need to set
your PGresult pointer to NULL after each PQclear().
So why doesn't PQclear() do that?

Because then PQclear() would need a ** not a *. Do you want its
interface changed for 9.3 and break compatibility with previous versions?
No, but we should introduce a new public API call that is safer,
otherwise we get people continually re-inventing new private APIs that
Do the Right Thing, as the two other respondents have shown.

How about these macros?
* Use do { } while (0) around the macros to get proper statement behaviour.
* The if() is not needed, both PQclear and PQfinish do it internally.
* Docs

Should the names show somehow that they are macros?
Or is it enough that it's mentioned in documentation?

Done. The fact that these are macros is mentioned in the docs.

--
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
Web: http://www.postgresql-support.de
     http://www.postgresql.at/

diff -durpN postgresql.3/doc/src/sgml/libpq.sgml postgresql.4/doc/src/sgml/libpq.sgml
--- postgresql.3/doc/src/sgml/libpq.sgml	2012-11-30 09:29:49.703286090 +0100
+++ postgresql.4/doc/src/sgml/libpq.sgml	2013-01-02 16:54:43.783565292 +0100
@@ -588,6 +588,27 @@ void PQfinish(PGconn *conn);
      </listitem>
     </varlistentry>
 
+    <varlistentry id="libpq-pqfinishsafe">
+     <term><function>PQfinishSafe</function><indexterm><primary>PQfinishSafe</></></term>
+     <listitem>
+      <para>
+       A macro that calls <function>PQfinish</function> and sets
+       the pointer to NULL afterwards.
+<synopsis>
+#define PQfinishSafe(conn) do { PQfinish(conn); conn = NULL; } while (0)
+</synopsis>
+      </para>
+
+      <para>
+       The <structname>PGconn</> pointer (being NULL) is safe to use
+       after this macro. Every function that deals with a
+       <structname>PGconn</> pointer considers a non-NULL pointer as valid.
+       Using a stale pointer may result in a crash. Setting the pointer
+       to NULL makes calling such functions a no-op instead.
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry id="libpq-pqreset">
      <term><function>PQreset</function><indexterm><primary>PQreset</></></term>
      <listitem>
@@ -2753,6 +2774,29 @@ void PQclear(PGresult *res);
        </para>
       </listitem>
      </varlistentry>
+
+     <varlistentry id="libpq-pqclearsafe">
+      <term><function>PQclearSafe</function><indexterm><primary>PQclearSafe</></></term>
+      <listitem>
+       <para>
+        A macro to call <function>PQclear</function> and set
+        the pointer to NULL afterwards.
+<synopsis>
+#define PQclearSafe(res) do { PQclear(res); res = NULL; } while (0)
+</synopsis>
+       </para>
+
+       <para>
+        Calling <function>PQclear</function> leaves a stale
+        <structname>PGresult</structname> pointer. Calling
+        functions that deal with <structname>PGresult</structname>
+        objects afterwards may result in a crash. Setting the
+        <structname>PGresult</structname> pointer to NULL makes
+        calling such functions a no-op instead.
+       </para>
+      </listitem>
+     </varlistentry>
+
     </variablelist>
    </para>
   </sect2>
diff -durpN postgresql.3/src/interfaces/libpq/libpq-fe.h postgresql.4/src/interfaces/libpq/libpq-fe.h
--- postgresql.3/src/interfaces/libpq/libpq-fe.h	2013-01-02 09:19:03.929522614 +0100
+++ postgresql.4/src/interfaces/libpq/libpq-fe.h	2013-01-02 16:52:41.236683245 +0100
@@ -256,6 +256,9 @@ extern PGconn *PQsetdbLogin(const char *
 /* close the current connection and free the PGconn data structure */
 extern void PQfinish(PGconn *conn);
 
+/* macro to close the current connection and set the conn pointer to NULL */
+#define PQfinishSafe(conn) do { PQfinish(conn); conn = NULL; } while (0)
+
 /* get info about connection options known to PQconnectdb */
 extern PQconninfoOption *PQconndefaults(void);
 
@@ -472,6 +475,9 @@ extern int	PQsendDescribePortal(PGconn *
 /* Delete a PGresult */
 extern void PQclear(PGresult *res);
 
+/* Macro to delete a PGresult and set the res pointer to NULL */
+#define PQclearSafe(res) do { PQclear(res); res = NULL; } while (0)
+
 /* For freeing other alloc'd results, such as PGnotify structs */
 extern void PQfreemem(void *ptr);
 
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to