summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2019-04-09 16:46:34 +0000
committerAlvaro Herrera2019-04-09 16:46:34 +0000
commitfe0e0b4fc7f0cdc2333bda08b199422a1e77a551 (patch)
treede4c2e661629a89fecbde874728020c30e1d0955
parenta2418f9e238794fcaaf00bbd5b8f953ca2856aa0 (diff)
Fix memory leak in pgbench
Commit 25ee70511ec2 introduced a memory leak in pgbench: some PGresult structs were not being freed during error bailout, because we're now doing more PQgetResult() calls than previously. Since there's more cleanup code outside the discard_response() routine than in it, refactor the cleanup code, removing the routine. This has little effect currently, since we abandon processing after hitting errors, but if we ever get further pgbench features (such as testing for serializable transactions), it'll matter. Per Coverity. Reviewed-by: Michaƫl Paquier
-rw-r--r--src/bin/pgbench/pgbench.c48
1 files changed, 18 insertions, 30 deletions
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 99529de52a..b67ad5e823 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -1214,20 +1214,6 @@ doConnect(void)
return conn;
}
-/* throw away response from backend */
-static void
-discard_response(CState *state)
-{
- PGresult *res;
-
- do
- {
- res = PQgetResult(state->con);
- if (res)
- PQclear(res);
- } while (res);
-}
-
/* qsort comparator for Variable array */
static int
compareVariableNames(const void *v1, const void *v2)
@@ -2732,6 +2718,7 @@ static bool
readCommandResponse(CState *st, char *varprefix)
{
PGresult *res;
+ PGresult *next_res;
int qrynum = 0;
res = PQgetResult(st->con);
@@ -2739,7 +2726,7 @@ readCommandResponse(CState *st, char *varprefix)
while (res != NULL)
{
/* look now at the next result to know whether it is the last */
- PGresult *next_res = PQgetResult(st->con);
+ next_res = PQgetResult(st->con);
bool is_last = (next_res == NULL);
switch (PQresultStatus(res))
@@ -2751,8 +2738,7 @@ readCommandResponse(CState *st, char *varprefix)
fprintf(stderr,
"client %d script %d command %d query %d: expected one row, got %d\n",
st->id, st->use_file, st->command, qrynum, 0);
- st->ecnt++;
- return false;
+ goto error;
}
break;
@@ -2764,10 +2750,7 @@ readCommandResponse(CState *st, char *varprefix)
fprintf(stderr,
"client %d script %d command %d query %d: expected one row, got %d\n",
st->id, st->use_file, st->command, qrynum, PQntuples(res));
- st->ecnt++;
- PQclear(res);
- discard_response(st);
- return false;
+ goto error;
}
/* store results into variables */
@@ -2788,10 +2771,7 @@ readCommandResponse(CState *st, char *varprefix)
"client %d script %d command %d query %d: error storing into variable %s\n",
st->id, st->use_file, st->command, qrynum,
varname);
- st->ecnt++;
- PQclear(res);
- discard_response(st);
- return false;
+ goto error;
}
if (*varprefix != '\0')
@@ -2807,10 +2787,7 @@ readCommandResponse(CState *st, char *varprefix)
"client %d script %d aborted in command %d query %d: %s",
st->id, st->use_file, st->command, qrynum,
PQerrorMessage(st->con));
- st->ecnt++;
- PQclear(res);
- discard_response(st);
- return false;
+ goto error;
}
PQclear(res);
@@ -2826,8 +2803,19 @@ readCommandResponse(CState *st, char *varprefix)
}
return true;
-}
+error:
+ st->ecnt++;
+ PQclear(res);
+ PQclear(next_res);
+ do
+ {
+ res = PQgetResult(st->con);
+ PQclear(res);
+ } while (res);
+
+ return false;
+}
/*
* Parse the argument to a \sleep command, and return the requested amount