BUG #5697: Infinite loop inside PQexecStart function - Mailing list pgsql-bugs

From Boris
Subject BUG #5697: Infinite loop inside PQexecStart function
Date
Msg-id 201010071410.o97EAI5j093356@wwwmaster.postgresql.org
Whole thread Raw
Responses Re: BUG #5697: Infinite loop inside PQexecStart function  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-bugs
The following bug has been logged online:

Bug reference:      5697
Logged by:          Boris
Email address:      admin@nyc.yamaha.com
PostgreSQL version: 8.3.5
Operating system:   Linux RH ES5
Description:        Infinite loop inside PQexecStart function
Details:

The infinite loop in this case occurs inside the PQexecStart() function in
pgsql driver. The following insert corresponds to the actual infinite loop.
The are several conditions that are checked "(result = PQgetResult(conn)) !=
NULL" and "result->resultStatus == PGRES_COPY_IN || result->resultStatus ==
PGRES_COPY_OUT || conn->status == CONNECTION_BAD" as an exit point.
---------------------------------------------------------
ASM code
0x0042bca5 in PQexecStart () from /usr/local/pgsql/lib/libpq.so.5
 17 0x0042bca5 <PQexecStart+37>: cmp $0x3,%esi
 18 0x0042bca8 <PQexecStart+40>: je 0x42bd00 <PQexecStart+128>
 19 0x0042bcaa <PQexecStart+42>: cmpl $0x1,0x44(%edi)
 20 0x0042bcae <PQexecStart+46>: je 0x42bcf0 <PQexecStart+112>
 21 0x0042bcb0 <PQexecStart+48>: mov %edi,(%esp)
 22 0x0042bcb3 <PQexecStart+51>: call 0x424fa0 <PQgetResult@plt>
 23 0x0042bcb8 <PQexecStart+56>: test %eax,%eax
 24 0x0042bcba <PQexecStart+58>: je 0x42bd13 <PQexecStart+147>
 25 0x0042bcbc <PQexecStart+60>: mov 0x1c(%eax),%esi
 26 0x0042bcbf <PQexecStart+63>: mov %eax,(%esp)
 27 0x0042bcc2 <PQexecStart+66>: call 0x4255d0 <PQclear@plt>
 28 0x0042bcc7 <PQexecStart+71>: cmp $0x4,%esi
 29 0x0042bcca <PQexecStart+74>: jne 0x42bca5 <PQexecStart+37>

---------------------------------------------------------
The C-code corresponding to this part (short version):
while ((result = PQgetResult(conn)) != NULL){
    ExecStatusType resultStatus = result->resultStatus;
    PQclear(result); /* only need its status */
    /* check for loss of connection, too */
    if (result->resultStatus == PGRES_COPY_IN ||
                         result->resultStatus == PGRES_COPY_OUT ||
                         conn->status == CONNECTION_BAD)
                         break;
    }
    return true;
---------------------------------------------------------
These are the values mapped to the corresponding constants:
PGRES_EMPTY_QUERY = 0
PGRES_COMMAND_OK = 1
PGRES_TUPLES_OK = 2
PGRES_COPY_OUT = 3
PGRES_COPY_IN = 4
PGRES_BAD_RESPONSE = 5
PGRES_NONFATAL_ERROR = 6
PGRES_FATAL_ERROR = 7

Condition exit point is evaluated against 3 constants PGRES_COPY_IN,
PGRES_COPY_OUT, CONNECTION_BAD. Since the connection to the database is in a
"GOOD" state the only constants that are evaluated are PGRES_COPY_IN and
PGRES_COPY_OUT, but according to the debugger trace the value those are
compared against is 7, e.g. PGRES_FATAL_ERROR which has no condition and
thus the process runs forever. Please see the following insert with detailed
output of the registers.
---------------------------------------------------------
0x0042bcc7 in PQexecStart () from /usr/local/pgsql/lib/libpq.so.5
1: x/i $pc 0x42bcc7 <PQexecStart+71>:    cmp $0x4,%esi
(gdb) i r
eax 0x99    153
ecx 0x1    1
edx 0x98    152
ebx 0x43a330    4432688
esp 0xbfe506d0    0xbfe506d0
ebp 0xbfe506e8    0xbfe506e8
esi 0x7    7
edi 0x98c5bb4    160193460
eip 0x42bcc7    0x42bcc7 <PQexecStart+71>
eflags 0x286    [ PF SF IF ]
cs 0x73    115
ss 0x7b    123
ds 0x7b    123
es 0x7b    123
fs 0x0    0
gs 0x33    51

pgsql-bugs by date:

Previous
From: Dave Page
Date:
Subject: Re: BUG #5696: cannot upgrade to 9.0.1
Next
From: Tom Lane
Date:
Subject: Re: BUG #5697: Infinite loop inside PQexecStart function