I try to explain this bug. Attached files contains example and patch
for libpq.

I hope, that you look at it and replay me what you think.

---
Segey N. Yatskevich <[EMAIL PROTECTED]>
#
# $Id$
#

ssl-async-query: ssl-async-query.cc
        c++ -g -I`pg_config --includedir` /usr/lib/libpq.so.3 -o ssl-async-query 
ssl-async-query.cc

clean:
        rm -f ssl-async-query
--- fe-secure.c.orig    2003-01-09 02:18:35 +0300
+++ fe-secure.c 2003-04-02 02:06:27 +0400
@@ -268,7 +268,10 @@
                        case SSL_ERROR_NONE:
                                break;
                        case SSL_ERROR_WANT_READ:
-                               n = pqsecure_read(conn, ptr, len);
+                               // I think this mean, that SSL layer have
+                               // no any data for us and we must try
+                               // to read it later.
+                               n = 0;
                                break;
                        case SSL_ERROR_SYSCALL:
                                printfPQExpBuffer(&conn->errorMessage,
@@ -314,7 +317,10 @@
                        case SSL_ERROR_NONE:
                                break;
                        case SSL_ERROR_WANT_WRITE:
-                               n = pqsecure_write(conn, ptr, len);
+                               // I think this mean, that SSL layer have
+                               // no free space for buffering our data and
+                               // we must try to write it later.
+                               n = 0;
                                break;
                        case SSL_ERROR_SYSCALL:
                                printfPQExpBuffer(&conn->errorMessage,
/*
 * SSL-test
 */
#include <iostream>
#include <libpq-fe.h>

static void
exit_nicely (PGconn *conn) {
        std::cerr << "ERROR: " << PQerrorMessage (conn) << '\n';

        PQfinish (conn);
        exit (1);
}

int
main (int _argc, char *_argv[]) {
        PGconn  *conn = PQconnectdb ("user=postgres dbname=template1 host=127.0.0.1 
requiressl=1");
        if (PQstatus (conn) == CONNECTION_BAD)
                exit_nicely (conn);

        PQsendQuery (conn, "select * from pg_class; select * from pg_type; select * 
from pg_proc");

        for (;;) {
                std::cout << "before DANGEROUS section of code\n";

#ifndef NO_STACK_OVERFLOW_DEMO
                // This is a DANGEROUS code. If we call PQconsumeInput here,
                // after getting last PGresult, we will go into infinite
                // recursive call of pqsecure_read on SSL_ERROR_WANT_READ.
                PQconsumeInput (conn);
                if (PQisBusy (conn))
                        continue;
                // Call PQcounsumeInput on SSL connection when server
                // don't send any data to us is DANGEROUS.
#else
                // This code is safe, becouse end of data determine before
                // call of PQconsumeInput and we don't go into pqsecure_read
                // when server have no data.
                if (PQisBusy (conn)) {
                        PQconsumeInput (conn);
                        continue;
                }
#endif
                // But I think PQconsumeInput must be safe to be called in
                // any time, becouse, for example, we can use it not only
                // for async query processing, but for getting asynhronous
                // notification from server in case when we don't send any
                // query to it and can't be sure, that server have data for
                // us.
                std::cout << "after DANGEROUS section of code\n";

                // When we don't use SSL this code in both case is completly
                // safe, becouse recv simple return 0 if no data avaliable.
                // I think this is good for SSL connection too.

                PGresult *res = PQgetResult (conn);
                if (res) {
                        if (PQresultStatus (res) == PGRES_TUPLES_OK)
                                std::cout << "SELECT\n";
                        else
                                std::cerr << "UNKNOWN\n";

                        PQclear (res);
                        continue;
                }

                break;
        }

        PQfinish(conn);
        return 0;
}
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org

Reply via email to