Re: Silent MALLOC/REALLOC error
"Inoue, Hiroshi" <[email protected]>
| Newsgroups | gmane.comp.db.postgresql.odbc |
|---|---|
| Message-ID | <[email protected]> |
Hi TAKATSUKA-san, sorry for the late reply. On 2018/02/27 18:33, TAKATSUKA Haruka wrote: > Hello, psqlODBC team. > > When we fetch large data via psqlodbc, we sometimes fail to > get all rows completely without any API's error responses; > SQLExecDirect returns SQL_SUCCESS and SQLFetch returns just SQL_NODATA. > But there are QR_REALLOC_error reported in mylog at that time. > > I reproduced it by tweaking QR_REALLOC_return_with_error macro > to intentionally fail to allocate memory frequently. > > I propose the patch attached. > It makes the code in CC_send_query_append() go out the while-loop immediately > after CC_from_PGresult() at the case PORES_BAD_RESPONSE, PORES_FATAL_ERROR or PORES_NO_MEMORY_ERROR. Thanks for the bug report. By applying your patch, subsequent queries after ALLOC errors are rejected unfortunately with the error message 'another command is already in progress'. I propose the patch attached. Does the patch work well in your test cases? regards, Hiroshi Inoue > > > Thanks, > Haruka Takatsuka
connection.diff
(text/plain, 1.8 KB)
diff --git a/connection.c b/connection.c
index ed51e02..52723b4 100644
--- a/connection.c
+++ b/connection.c
@@ -1750,6 +1750,7 @@ CC_send_query_append(ConnectionClass *self, const char *query, QueryInfo *qi, UD
discard_next_savepoint = FALSE,
discard_next_release = FALSE,
consider_rollback;
+ BOOL discardTheRest = FALSE;
int func_cs_count = 0;
PQExpBufferData query_buf = {0};
size_t query_len;
@@ -1922,6 +1923,8 @@ CC_send_query_append(ConnectionClass *self, const char *query, QueryInfo *qi, UD
{
int status = PQresultStatus(pgres);
+ if (discardTheRest)
+ continue;
switch (status)
{
case PGRES_COMMAND_OK:
@@ -2088,15 +2091,16 @@ MYLOG(DETAIL_LOG_LEVEL, "Discarded a RELEASE result\n");
if (cursor && cursor[0])
QR_set_synchronize_keys(res);
}
- if (!CC_from_PGresult(res, stmt, self, cursor, &pgres))
+ if (CC_from_PGresult(res, stmt, self, cursor, &pgres))
+ query_completed = TRUE;
+ else
{
+ aborted = TRUE;
if (QR_command_maybe_successful(res))
retres = NULL;
else
retres = cmdres;
- aborted = TRUE;
}
- query_completed = TRUE;
}
else
{ /* next fetch, so reuse an existing result */
@@ -2117,6 +2121,20 @@ MYLOG(DETAIL_LOG_LEVEL, "Discarded a RELEASE result\n");
{
QR_set_rstatus(res, PORES_NONFATAL_ERROR);
}
+ else if (PORES_NO_MEMORY_ERROR == QR_get_rstatus(res))
+ {
+ PGcancel *cancel;
+ char dummy[8];
+
+ discardTheRest = TRUE;
+ if (cancel = PQgetCancel(self->pqconn))
+ {
+ PQcancel(cancel, dummy, sizeof(dummy));
+ PQfreeCancel(cancel);
+ }
+ else
+ goto cleanup;
+ }
break;
case PGRES_COPY_OUT:
/* XXX: We used to read from stdin here. Does that make any sense? */