From e77aaade349e3947a55c41f07eb80c4f5260ada4 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 6 Jul 2001 17:58:53 +0000 Subject: [PATCH] Repair libpq to follow protocol by not sending Terminate messages before the startup exchange is complete. Also make sure that packets defined as single bytes aren't sent with a trailing '\0'. --- src/interfaces/libpq/fe-connect.c | 12 ++++++++---- src/interfaces/libpq/fe-exec.c | 18 ++++++++---------- src/interfaces/libpq/fe-misc.c | 20 +++++++++++++++++++- src/interfaces/libpq/libpq-int.h | 4 +++- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 18770f49f5..7fda1a81f5 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.164 2001/03/31 23:14:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.165 2001/07/06 17:58:53 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1409,6 +1409,7 @@ keep_going: /* We will come back to here until there if (areq == AUTH_REQ_OK) { /* We are done with authentication exchange */ + conn->startup_complete = TRUE; conn->status = CONNECTION_AUTH_OK; /* @@ -1909,6 +1910,7 @@ makeEmptyPGconn(void) freePGconn(conn); conn = NULL; } + conn->startup_complete = FALSE; return conn; } @@ -1972,7 +1974,9 @@ freePGconn(PGconn *conn) static void closePGconn(PGconn *conn) { - if (conn->sock >= 0) + /* Note that the protocol doesn't allow us to send Terminate + messages during the startup phase. */ + if (conn->sock >= 0 && conn->startup_complete) { /* @@ -1981,8 +1985,8 @@ closePGconn(PGconn *conn) * avoid getting SIGPIPE'd if the connection were already closed. * Now we rely on pqFlush to avoid the signal. */ - (void) pqPuts("X", conn); - (void) pqFlush(conn); + pqPutc('X', conn); + pqFlush(conn); } /* diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index e7838315ec..78d5736908 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.101 2001/02/10 02:31:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.102 2001/07/06 17:58:53 petere Exp $ * *------------------------------------------------------------------------- */ @@ -556,8 +556,7 @@ PQsendQuery(PGconn *conn, const char *query) return 0; /* 'Q' == queries */ /* XXX: if we fail here we really ought to not block */ - if (pqPutnchar("Q", 1, conn) || - pqPuts(query, conn)) + if (pqPutc('Q', conn) != 0 || pqPuts(query, conn) != 0) { handleSendFailure(conn); return 0; @@ -567,7 +566,7 @@ PQsendQuery(PGconn *conn, const char *query) * give the data a push, ignore the return value as ConsumeInput() * will do any aditional flushing if needed */ - (void) pqFlush(conn); + pqFlush(conn); } else { @@ -575,9 +574,8 @@ PQsendQuery(PGconn *conn, const char *query) /* * the frontend-backend protocol uses 'Q' to designate queries */ - if (pqPutnchar("Q", 1, conn) || - pqPuts(query, conn) || - pqFlush(conn)) + if (pqPutc('Q', conn) != 0 || pqPuts(query, conn) != 0 || + pqFlush(conn) != 0) { handleSendFailure(conn); return 0; @@ -1655,9 +1653,9 @@ PQfn(PGconn *conn, return NULL; } - if (pqPuts("F ", conn) || /* function */ - pqPutInt(fnid, 4, conn) || /* function id */ - pqPutInt(nargs, 4, conn)) /* # of args */ + if (pqPuts("F ", conn) != 0 || /* function */ + pqPutInt(fnid, 4, conn) != 0 || /* function id */ + pqPutInt(nargs, 4, conn) != 0) /* # of args */ { handleSendFailure(conn); return NULL; diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 04be4bb692..bcc3bdc9c8 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -25,7 +25,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.49 2001/05/28 15:29:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.50 2001/07/06 17:58:53 petere Exp $ * *------------------------------------------------------------------------- */ @@ -59,6 +59,8 @@ #define DONOTICE(conn,message) \ ((*(conn)->noticeHook) ((conn)->noticeArg, (message))) +static int pqPutBytes(const char *s, size_t nbytes, PGconn *conn); + /* --------------------------------------------------------------------- */ /* pqGetc: @@ -83,6 +85,22 @@ pqGetc(char *result, PGconn *conn) } +/* + * write 1 char to the connection + */ +int +pqPutc(char c, PGconn *conn) +{ + if (pqPutBytes(&c, 1, conn) == EOF) + return EOF; + + if (conn->Pfdebug) + fprintf(conn->Pfdebug, "To backend> %c\n", c); + + return 0; +} + + /* --------------------------------------------------------------------- */ /* pqPutBytes: local routine to write N bytes to the connection, with buffering diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 2c652bd767..a33176e6da 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq-int.h,v 1.33 2001/03/22 04:01:27 momjian Exp $ + * $Id: libpq-int.h,v 1.34 2001/07/06 17:58:53 petere Exp $ * *------------------------------------------------------------------------- */ @@ -278,6 +278,7 @@ struct pg_conn PQExpBufferData workBuffer; /* expansible string */ int client_encoding;/* encoding id */ + int startup_complete; }; /* String descriptions of the ExecStatusTypes. @@ -313,6 +314,7 @@ extern void pqClearAsyncResult(PGconn *conn); * necessarily any error. */ extern int pqGetc(char *result, PGconn *conn); +extern int pqPutc(char c, PGconn *conn); extern int pqGets(PQExpBuffer buf, PGconn *conn); extern int pqPuts(const char *s, PGconn *conn); extern int pqGetnchar(char *s, size_t len, PGconn *conn);